我最近研究了C中的malloc(),声明如下:
void *malloc(size_t size)
其中CCD_ 1是无符号int,而CCD_。问题是,在我的系统上,float值占用了4字节的内存。因此,如果我使用2字节的malloc制作内存指针(浮点型),
float *p;
p = (float *)malloc(2);
那么为什么它没有给出任何错误呢?因为我认为浮点数据需要4个字节,所以如果我只向它发出2个字节,那么可能会导致一些数据丢失。
还是我对malloc()的理解不正确?
在您给出的示例中,如果您只为float *
分配了2个字节,然后试图通过取消引用指针来写入该位置,那么您将写入尚未分配的内存。这会导致未定义的行为。这意味着它可能会工作,它可能会进行核心转储,或者它可能会以不可预测的方式表现。
如果你想为一个或多个浮点分配内存,你可以这样做:
// allocates space for an array of 5 floats
// don't cast the result of malloc
int arrayLen = 5;
float *f = malloc(sizeof(float) * arrayLen);
您遇到了C标准要求的特定于实现的结果:
7.22.3内存管理功能
对的连续调用所分配的存储的顺序和邻接性
aligned_alloc
、calloc
、malloc
和realloc
功能未指定如果分配成功,则返回的指针为适当对齐,以便可以将其分配给指向任何类型的指针具有基本对齐要求的对象的,然后用于访问空间中的此类对象或此类对象的阵列已分配(直到明确释放空间为止)。
为了提供"适当对齐的存储,以便可以将其分配给具有基本对齐要求的任何类型对象的指针",实现必须以系统最严格对齐要求的倍数的特定偏移从malloc()
等人返回内存。这通常是8或16个字节。
考虑到每个返回的块都必须以这种方式对齐,大多数实现在内部创建的内存块是对齐要求的倍数。
因此,如果您的系统有8字节的对齐要求,那么即使您请求了两个字节,malloc()
实现也可能实际为您提供8字节的内存块。同样,要求19个字节,实际上你可能会得到24个字节。
然而,超出你的要求仍然是一种未定义的行为。不幸的是,未定义的行为确实包括"工作正常"。
如果你试图使用该指针,这可能会有问题——实际上指针很好,是它所指向的分配内存太小了——编译器没有将其识别为错误的原因是指针没有"意识到"它指向的是什么,实际上指针是包含内存地址的变量,所以基本上它们只是一个数字,在大多数情况下(正如user694733所指出的),无论指针指向空头还是浮点,指针的大小都是相同的。编译器看到的是从(void*)到(float*)的强制转换,对编译器来说,这是一个完全有效的强制转换。
您的问题实际上与malloc无关,而是与数据转换有关。在这种情况下,您已经将从malloc返回的地址开始定位的字节强制转换为float。因此,如果您稍后说size_t
0,您实际上将向上述内存区域写入4个字节,但由于您只分配了2个字节,因此只有2个字节可供使用。因此,您的代码将在内存损坏的情况下编译和运行(这可能会导致崩溃,或者稍后出现意外的运行时行为)