可以在 malloc 缓冲区上执行整数运算(例如加法或减法)吗?
Can integer operations (eg addition or subtraction) be performed on malloc buffers?
为了了解 JPEG 压缩,我下载了一个我一直在研究的简单 BMP/JPEG encoder。我有几个问题,希望有人能帮助我。我不是训练有素的计算机科学家,只是业余爱好的程序员。感谢您的帮助。
以下代码读取位图,为简洁起见,我省略了一些信息。我知道位图 header 被写成一个结构,所以组件可以直接读取到变量而无需迭代。
BYTE 是 uint8_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?
}
我将我的问题作为代码中的注释,并粘贴在下面。
加法是为了什么?我认为这与填充 BMP 文件有关。不加就有总线错误:10
pdata = (BYTE*)pb->pdata + pb->stride * pb->height;
减法是为了什么?
pdata -= pb->stride;
最后,为什么返回的是 pb->pdata 而实际上是在代码中修改的 pdata?
这是将数据从文件 file
读取到缓冲区 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
将指向第一个块要放置的位置,填充 缓冲区的 last pb->stride
字节。在连续的迭代中,pdata
继续递减,以相反的顺序将块写入缓冲区,直到最后一个块被放置在缓冲区的开头 pb->pdata
.
如果省略初始加法,则 pdata
将开始指向缓冲区的 beginning,然后减法会使它指向 before 缓冲区的开始。然后尝试在该位置读取将越界,这不足为奇地导致崩溃。
请注意,该函数实际上并不是 returning pb->pdata
,而是 pb->pdata ? 0 : -1
。这是使用 C 三元运算符 并表示如果 pb->pdata
为非 NULL,则 return 0
,否则 return -1
。现在 pb->pdata
只有在之前的 malloc
失败(即没有内存可用)时才会为 NULL,在这种情况下,整个读取循环将被 if (pb->pdata)
跳过。所以这实际上是 returning 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
减少,因为 pixels are usually stored "bottom-up"(至少在 BMP 中)。
为了了解 JPEG 压缩,我下载了一个我一直在研究的简单 BMP/JPEG encoder。我有几个问题,希望有人能帮助我。我不是训练有素的计算机科学家,只是业余爱好的程序员。感谢您的帮助。
以下代码读取位图,为简洁起见,我省略了一些信息。我知道位图 header 被写成一个结构,所以组件可以直接读取到变量而无需迭代。
BYTE 是 uint8_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?
}
我将我的问题作为代码中的注释,并粘贴在下面。 加法是为了什么?我认为这与填充 BMP 文件有关。不加就有总线错误:10
pdata = (BYTE*)pb->pdata + pb->stride * pb->height;
减法是为了什么?
pdata -= pb->stride;
最后,为什么返回的是 pb->pdata 而实际上是在代码中修改的 pdata?
这是将数据从文件 file
读取到缓冲区 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
将指向第一个块要放置的位置,填充 缓冲区的 last pb->stride
字节。在连续的迭代中,pdata
继续递减,以相反的顺序将块写入缓冲区,直到最后一个块被放置在缓冲区的开头 pb->pdata
.
如果省略初始加法,则 pdata
将开始指向缓冲区的 beginning,然后减法会使它指向 before 缓冲区的开始。然后尝试在该位置读取将越界,这不足为奇地导致崩溃。
请注意,该函数实际上并不是 returning pb->pdata
,而是 pb->pdata ? 0 : -1
。这是使用 C 三元运算符 并表示如果 pb->pdata
为非 NULL,则 return 0
,否则 return -1
。现在 pb->pdata
只有在之前的 malloc
失败(即没有内存可用)时才会为 NULL,在这种情况下,整个读取循环将被 if (pb->pdata)
跳过。所以这实际上是 returning 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
减少,因为 pixels are usually stored "bottom-up"(至少在 BMP 中)。