可以在malloc缓冲区上执行整数运算(如加法或减法)吗?

可以在malloc缓冲区上执行整数运算(如加法或减法)吗?,c,bmp,C,Bmp,为了了解JPEG压缩,我下载了一个简单的BMP/JPEG,我一直在研究它。我有几个问题,希望有人能帮我解决。我不是一个受过训练的计算机科学家,只是一个爱好程序员。谢谢你的帮助 下面的代码读取位图,为了简洁起见,我遗漏了一些信息。我知道位图头是作为结构编写的,因此组件可以直接读取到变量,而无需迭代 BYTE是uint8\u t的类型定义 int bmp_load(BMP *pb, char *file) { BMPFILEHEADER header = {0}; FILE

为了了解JPEG压缩,我下载了一个简单的BMP/JPEG,我一直在研究它。我有几个问题,希望有人能帮我解决。我不是一个受过训练的计算机科学家,只是一个爱好程序员。谢谢你的帮助

下面的代码读取位图,为了简洁起见,我遗漏了一些信息。我知道位图头是作为结构编写的,因此组件可以直接读取到变量,而无需迭代

BYTE是uint8\u t的类型定义

    int bmp_load(BMP *pb, char *file)
{
    BMPFILEHEADER header = {0};
    FILE         *fp     = NULL;
    BYTE         *pdata  = NULL;
    int           i;

    fp = fopen(file, "rb");
    if (!fp) return -1;

    fread(&header, sizeof(header), 1, fp);
    pb->width  = header.biWidth;
    pb->height = header.biHeight;
    pb->stride = ALIGN(header.biWidth * 3, 4);
    pb->pdata  = malloc(pb->stride * pb->height);// allocate a byte for each element of bitmap?
    if (pb->pdata) {
        pdata  = (BYTE*)pb->pdata + pb->stride * pb->height; // Title question: Cast pdata as uint8_t buffer but what is the addition for? I think it has to do with padding a BMP file.  Without addition there is a bus error: 10 
        for (i=0; i<pb->height; i++) {
            pdata -= pb->stride; // What is the subtraction for? 
            fread(pdata, pb->stride, 1, fp);
        }
    }

    fclose(fp);
    return pb->pdata ? 0 : -1; // If pdata was being modified in the for loop, why is pb->pdata returned? 
}

减法是什么意思

    pdata -= pb->stride;

最后,为什么pb->pdata返回,但实际上是在代码中修改的pdata

这是将数据从文件
文件
读入缓冲区
pb->pdata
,按大小
pb->stride
的相反顺序读取。块的数量是
pb->height

指针
pdata
用于指示下一个块将放置在缓冲区中的位置。由于缓冲区的总大小为
pb->stride*pb->height
,因此

pdata  = (BYTE*)pb->pdata + pb->stride * pb->height;
pdata
设置为指向缓冲区的末尾
pb->pdata
(即指向最后一个缓冲区后面的元素)。在循环的第一次迭代中,当从
pdata
中减去
pb->stride
时,
pdata
将指向放置第一个块的位置,填充缓冲区的最后一个
pb->stride
字节。在连续的迭代中,
pdata
继续递减,以相反的顺序将块写入缓冲区,直到最后一个块放置在缓冲区的开始处
pb->pdata

如果省略初始加法,则
pdata
将开始指向缓冲区的开始,减法将使其指向缓冲区的开始之前。然后,尝试在该位置读取将是不允许的,这会导致崩溃


请注意,函数实际上并没有返回
pb->pdata
,而是返回
pb->pdata?0:-1
。这是使用C三元运算符,表示如果
pb->pdata
为非空,则返回
0
,否则返回
-1
。现在
pb->pdata
只有在前面的
malloc
失败(即没有可用内存)时才会为空,在这种情况下
if(pb->pdata)
将跳过整个读取循环。因此,这实际上是返回0表示成功,返回-1表示失败,这也是一个常见的习惯用法。

这里是对函数的重写,可能更容易理解

int bmp_load(BMP *pb, char *file)
{
    FILE* = fopen(file, "rb");
    if (!fp) return -1;

    BMPFILEHEADER header;
    fread(&header, sizeof(header), 1, fp);
    pb->width = header.biWidth;
    pb->height = header.biHeight;
    pb->stride = ALIGN(header.biWidth * 3, 4);
    pb->pdata = malloc(pb->stride * pb->height);

    if (!pb->pdata) return -1;

    for (int i = pb->height - 1; i >= 0; i--) {
        BYTE* pdata_current_row = pb->pdata + pb->stride * i;
        fread(pdata_current_row, pb->stride, 1, fp);
    }

    fclose(fp);
    return 0;
}

for循环的
i
减少,因为(至少在BMP中)。

BMP\u load
不返回
pb->pdata
。它根据
pb->pdata
的值返回
0
-1
。非常感谢。那么缓冲区上的算术运算是用来设置指针位置的呢?非常感谢,非常感谢你花时间写这篇文章。我很清楚,
BYTE*pdata\u current\u row=pb->pdata+pb->stride*I将pdata\u current\u行指针设置为pb->stride*I处的缓冲区点?Thanks@m_ridge对
pb->pdata+pb->stride*i
相当于
&pb->pdata[pb->stride*i]
。它只是为内存中的那个位置创建一个临时别名。在我的重写中,您也可以去掉
pdata\u current\u row
,只需调用
fread(&pb->pdata[pb->stride*i],pb->stride,1,fp)
int bmp_load(BMP *pb, char *file)
{
    FILE* = fopen(file, "rb");
    if (!fp) return -1;

    BMPFILEHEADER header;
    fread(&header, sizeof(header), 1, fp);
    pb->width = header.biWidth;
    pb->height = header.biHeight;
    pb->stride = ALIGN(header.biWidth * 3, 4);
    pb->pdata = malloc(pb->stride * pb->height);

    if (!pb->pdata) return -1;

    for (int i = pb->height - 1; i >= 0; i--) {
        BYTE* pdata_current_row = pb->pdata + pb->stride * i;
        fread(pdata_current_row, pb->stride, 1, fp);
    }

    fclose(fp);
    return 0;
}