int *p = (int *)malloc(4);
*p = 100;
因为 sizeof(int) 对我而言返回的是 4。
然而,如果我执行以下操作:
int *p = (int *)malloc(1);
*p = 100;
看起来它的工作方式完全相同,没有存储价值的问题。
为什么用malloc()请求的内存量似乎不重要?一个4字节的整数不应该需要malloc(4)吗?
malloc
和free
的频率更高,这种情况仍然可能发生。malloc
通常会拿走比请求的内存多一些的字节,并使用额外的空间来管理(所有内存块的链接列表,内存块的大小)。如果你在分配的块之前或之后写入一些字节,那么你会很容易干扰内部管理结构,并且随后的malloc
或free
将会崩溃。malloc
是C语言运行时库或操作系统内核中的所有内存块分配函数,它们都针对于内存访问和对象对齐进行了优化。
此外,malloc
特别地在所分配的空间前面分配了一个隐藏的控制块来跟踪分配情况(所需空间,已分配空间等)。
malloc
必须确保所分配的内存地址适合于任何存储对象的存储,这意味着所分配的内存块将以8、16、32甚至64或128字节边界开始,具体取决于处理器和硬件(例如一些特殊MMU)。该边界还取决于访问速度,某些处理器在不同的内存访问(1、2、4、8等字节)和地址边界下有不同的行为。这些约束条件驱动着malloc
代码规范和分配器逻辑内存块的划分。
从实际角度考虑,假设我们使用X86处理器的分配器,它通常返回一个按照8字节边界对齐的块(32位代码),这对于int、float甚至double类型非常有用。为了实现这一点,malloc
将可用的内存竞技场划分为“块”,它们是最小的分配空间。当你分配1个字节时,该函数至少分配一个块。最终,此块可以容纳一个整数,甚至是一个double类型,但这取决于具体实现,不能视为确定性的,因为在同一函数的未来版本中行为可能会更改。
现在,我希望您已经清楚了,因为您的代码似乎可以工作,请牢记这是未定义的行为,您必须保持它的状态。它现在可能能够工作,但在下一个版本中就不行了,它可能会在某些硬件上崩溃,而在另一个处理器或机器上则不会。
C编程语言赋予了你踢自己脚的能力。
它有意让程序员承担起应该知道自己在做什么的责任。总的来说,这是为了实现性能、可读性和可移植性。
你的代码行为是未定义的。如果你请求1个字节,那么只能得到一个可用的字节。操作系统和C运行库似乎给了你更多,但这只是一个奇怪的特殊情况。
在其他情况下,编译器可能会吃掉你的猫。
最后,在调用malloc
时使用sizeof
而不是硬编码int
类型的大小:在许多系统上,sizeof(int)
是2,4是常见的,所有大于1的值都被标准允许。在你的情况下,使用sizeof(int)
或sizeof(*p)
都是可能的。有些人更喜欢后者,因为这样你就不需要在sizeof
调用中硬编码变量类型,从而防止可能的变量类型更改。(请注意,sizeof(*p)
是编译时可计算的,并使用静态类型信息;因此,如果你明白我的意思,它可以在p
本身“存在”之前使用。)
看起来它完全一样,存储值没有问题。
您的代码存在未定义行为,因此无法确定其是否有效。要为整数分配内存,应该执行以下操作:
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;
int *p = malloc(sizeof *p)
。 - Some programmer dudesizeof *p
,而不是 sizeof(p)
,这是指针的大小。 - mchsizeof
调用中引用 *p
的注意事项会很有帮助。这是一个好答案。 - Bathshebap
之前使用 sizeof (*p)
看起来很奇怪。 - Bathshebamalloc
的实现方式是分配不小于16字节的段大小内存。因此,当您需要4字节的内存时,malloc
实际上会分配16字节的内存。然而,这种行为在C标准中没有描述,您不能依赖它。因此,这意味着您展示的程序具有未定义的行为。我认为这是由于填充造成的,即使您调用malloc(1)
,填充字节也会随内存一起出现。请查看此链接http://www.delorie.com/gnu/docs/glibc/libc_31.html。
malloc
结果的讨论。链接为:https://dev59.com/dHRB5IYBdhLWcg3wgHWr - Some programmer dudemalloc
通常返回对齐于最大数据类型的指针(通常为8或16字节),因此在大多数实现中,分配几个字节会分配至少8或16字节。 - Marian