2016-01-13 183 views
-1

我最近研究关于的malloc()在下用声明如下:兼容性()

void *malloc(size_t size) 

其中size_t是无符号的int和size定义没有。的字节被保留。 问题是在我的系统上 float值占用4字节的内存。所以,如果我使用2bytes的malloc的内存指针(浮点型),

float *p; 
p = (float *)malloc(2); 

那么它怎么没有给出任何错误?因为我认为浮点数据需要4个字节,所以如果我只发出2个字节,那么它可能会导致一些数据丢失。

还是我理解malloc()不正确?

+1

'size_t'不一定是'unsigned int'。不要依赖它。例如。在具有16位'int'但32个指针的系统上,它可能是'unsigned long'。在x64上它可能是'unsigned long long'(Windows,LLP64)或'unsigned long'(POSIX64,LP64)。 – Olaf

+0

您确实已经回答了您的问题。再读一遍,看看你认为错的地方。记住C不会妨碍你(很多)射击你的脚。 – Olaf

+0

我更关心问题的后半部分 – Lincoln

回答

2

在您给出的示例中,如果您只为float *分配2个字节,然后尝试通过取消引用指针来写入该位置,则会写入尚未分配的内存。这导致undefined behavior。这意味着它可能工作,它可能会转储核心,或者它可能以不可预知的方式运行。

如果你想为一个或多个浮标分配内存时,你会做这样的:

// allocates space for an array of 5 floats 
// don't cast the result of malloc 
int arrayLen = 5; 
float *f = malloc(sizeof(float) * arrayLen); 
1

如果您尝试使用该指针 - 实际上指针正常,它指向的分配内存太小 - 编译器无法将其识别为错误的原因是这样的一个事实,指针并不“知道”它指向的内容,实际上指针是包含内存地址的变量,所以基本上它们只是一个数字,并且在大多数情况下(如user694733指出的),指针的大小是相同的无论是指向一个空头还是一个浮动。 编译器看到的是从(void *)到(float *)的转换以及编译器,这是一个完全有效的转换。

+0

*“指针的大小是相同的,无论它指向一个短的还是浮动的”*不一定。他们被允许有不同的内部表示。这里'void *'被*转换为'float *'。 – user694733

+0

@ user694733指针本身是内存地址,所以它们在同一台机器上具有相同的大小,而不管它们指向什么。明确的演员阵容可以 - 在我看来应该放弃。 –

+0

应该删除显式转换,因为当'void *'被分配给其他指针类型时,C会执行*隐式转换*。许多现代系统对所有指针类型使用相同的提示,但它不是C标准所要求的:可能仍然存在隐式转换。 – user694733

0

你的问题实际上已经无关malloc的,而是在数据广播。在这种情况下,您已将从malloc返回的地址开始的字节转换为float。因此,如果您稍后说*p = 0.0f;,您实际上会向所提及的内存区域写入4个字节,但由于您只分配了2个字节,所以只需要2个字节就可以使用。因此,您的代码将编译和内存损坏运行(这要么会导致死机,或更高版本的系统异常行为)

1

您遇到的C Standard的要求执行特定的结果:

7.22.3存储器管理功能

的顺序和由连续调用分配给 的aligned_alloccallocmalloc,和realloc福存储的邻接没有指定 。 如果分配成功返回的指针是 适当对齐,以便它可以被分配到指向任何类型的指针 对象具有基本对齐要求然后用于访问这样的对象或这样的对象数组分配空间 (直到空间明确释放)。

为了提供存储“适当地对准,使得它可以被分配给一个指针到任何类型的对象与基本对齐要求”,一个实施方案具有从malloc()在特定偏移返回存储器这是系统最严格的对齐要求的倍数。这通常是8或16个字节。

鉴于返回每一个块具有被对准这样,大多数实现在内部的对齐要求倍数创建的存储器块。

所以如果你的系统有8字节对齐要求,你的malloc()实现可能实际上给你一个8字节的内存块,即使你请求了两个字节。同样,要求19个字节,实际上你可能会得到24个字节。

它仍然不确定的行为超越你问什么,但。不幸的是,未定义的行为包括“工作得很好”。