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