int *p;
p = malloc(sizeof (*p) ); //you can use sizeof(*p) as p is already declared and here you use the size of its content, which is actually the size of an int
if (p != NULL)
*p = 100;
而且, malloc 具体地说,在分配的空间前分配一个隐藏的控制块来跟踪分配(所需的空间, space allocated 等) .
malloc must also to guarantee that the allocated memory address is suitably aligned for any storage object ,这意味着该块将以8,16,32或甚至64或128字节的边界开始,具体取决于处理器,一般来自硬件(即一些特殊的MMU) . 边界也取决于访问速度,某些处理器具有不同的行为,具有不同的存储器访问(1,2,4,8,...字节)和地址边界 . 此约束驱动 malloc 代码规范和分配器逻辑内存块分区 .
在实际的一面让我们考虑一个X86处理器的分配器,它通常会返回一个在8字节边界(32位代码)上对齐的块,这对于int,float和even double都很有用 . 为此, malloc 将'blocks'中可用的内存区域划分为最小分配空间 . 当您分配甚至1个字节时,该函数至少分配一个块 . 最终,这个块可以承载一个整数,甚至是一个双精度 but it is implementation dependent, and you can't consider it deterministic ,因为在同一函数的未来版本中,行为可以改变 .
现在,我希望,这很清楚,因为你的代码似乎有效,请记住 this is Undefined-Behavior and you must keep it for that . IT现在可以工作,而不是下一次修订,它可以在某些硬件上崩溃而在另一台处理器或机器上崩溃 .
6 回答
如果这适用于您的情况,它只是偶然工作,并不保证工作 . 这是未定义的行为(比较this SO question),一切都可能发生 .
你期望发生什么?你的程序崩溃了?
如果你经常调用
malloc
和free
,这可能仍然会发生 .malloc
经常比请求多占用一些字节,并使用额外的空间进行管理(所有内存块的链表,内存块的大小) . 如果你在分配的块之前或之后写了一些字节,那么你很可能会混淆内部管理结构,而后续的free
会崩溃 .如果malloc内部总是分配最少n个字节,那么如果访问字节n 1,程序可能只会崩溃 . 此外,操作系统通常只能根据页面保护内存 . 如果一个页面的大小为512字节,并且您的malloc-ed字节位于页面中间,那么您的进程可能能够读写页面的其余部分,并且只会在访问下一个内存页面时崩溃 . 但要记住:即使这有效,也是未定义的行为 .
C编程语言使您能够用脚射击自己 .
它故意给程序员带来负担,他们应该知道他们在做什么 . 从广义上讲,原因是要实现性能,可读性和可移植性 .
代码的行为未定义 . 如果要求1个字节,则期望只返回一个可用字节 . 事实上,操作系统和C运行时库似乎给你的回馈多一点,这只不过是一种奇怪的特性 .
在其他情况下,编译器可能只是吃你的猫 .
最后,在
malloc
的调用中使用sizeof
而不是硬编码int
类型的大小:在许多系统上sizeof(int)
是2,4是常见的,并且标准允许所有大于1的值 . 在您的情况下,可以使用sizeof(int)
或sizeof(*p)
. 有些人喜欢后者,因为那时你并没有在sizeof
调用中硬编码变量的类型,所以要防止可能的变量类型更改 . (注意sizeof(*p)
是编译时可评估的并且使用静态类型信息;因此如果你理解了它,它可以在p
本身"exists"之前使用 . )您使用代码调用未定义的行为,因此您无法确定它是否有效 . 为了为整数分配内存,你应该这样做:
通常
malloc
的实现方式是它分配的内存大小不小于段落大小等于16个字节 . 所以当你需要例如4字节的内存时malloc
实际上分配了16个字节 . 但是,此行为未在C标准中描述,您可能不会依赖它 . 因此,这意味着您显示的程序具有未定义的行为 .我认为这是因为填充,即使你正在调用
malloc(1)
填充字节随内存一起提供 . 请检查此链接http://www.delorie.com/gnu/docs/glibc/libc_31.htmlmalloc
,因为来自C运行时或OS内核的所有内存块分配函数都针对内存访问和对象对齐进行了优化 .而且,
malloc
具体地说,在分配的空间前分配一个隐藏的控制块来跟踪分配(所需的空间, space allocated 等) .malloc must also to guarantee that the allocated memory address is suitably aligned for any storage object ,这意味着该块将以8,16,32或甚至64或128字节的边界开始,具体取决于处理器,一般来自硬件(即一些特殊的MMU) . 边界也取决于访问速度,某些处理器具有不同的行为,具有不同的存储器访问(1,2,4,8,...字节)和地址边界 . 此约束驱动
malloc
代码规范和分配器逻辑内存块分区 .在实际的一面让我们考虑一个X86处理器的分配器,它通常会返回一个在8字节边界(32位代码)上对齐的块,这对于int,float和even double都很有用 . 为此,
malloc
将'blocks'中可用的内存区域划分为最小分配空间 . 当您分配甚至1个字节时,该函数至少分配一个块 . 最终,这个块可以承载一个整数,甚至是一个双精度 but it is implementation dependent, and you can't consider it deterministic ,因为在同一函数的未来版本中,行为可以改变 .现在,我希望,这很清楚,因为你的代码似乎有效,请记住 this is Undefined-Behavior and you must keep it for that . IT现在可以工作,而不是下一次修订,它可以在某些硬件上崩溃而在另一台处理器或机器上崩溃 .