malloc()文档说返回的指针适合于任何类型的变量。在我的系统上,long double的大小为12,但malloc()返回的一些指针在8字节边界上对齐而不是12(ptr%12给出4)。谁能指出我在这里失踪了什么?提前谢谢。
答案 0 :(得分:5)
显然,long double
不需要与12个字节对齐。在像你这样的系统上,原始C类型的最大对齐是double
的8个字节。不要混淆对齐和大小 - 虽然许多较小的(特别是原始的)类型必须自然对齐 - 也就是说,与它们自己的大小对齐 - 这对于较大的数据类型(想想碎片)是禁止的,并且不会使任何更容易硬件
答案 1 :(得分:4)
在gcc
for Linux和x86
上有:
sizeof (long double) == 12
和
在gcc
上用于Linux,x64
用于:
sizeof (long double) == 16
x64
long double
的ABI对齐要求是16
- 字节。对于x86
,任何类型都不需要超过8
个字节的对齐。
要尊重glibc
malloc
返回与8
对齐的内存对象 - 32-bit
系统上的字节并在16
上对齐 - 64
的字节} -bit systems。
来自glibc
doc:
malloc为您提供的块保证对齐,以便它可以保存任何类型的数据。在GNU系统上,地址在大多数系统上始终是8的倍数,在64位系统上是16的倍数。
答案 2 :(得分:3)
在任何理智的cpu体系结构中,对于大小为12的对象,最大可能的对齐要求是4.对齐要求必须是2的幂,才能均匀地划分类型的大小。实际上,这会给出非常差的对齐(跨越缓存行甚至页面的对象!),这就是x86_64 ABI将long double
的大小更改为16的原因:这样就可以将它对齐而不是跨越任何边界。
答案 3 :(得分:0)
malloc
将为任何类型返回正确对齐的内存,因为它返回的指针通常会转换为任意类型的指针,这种转换通常(读取:无限接近100%的时间)a无操作。对于任何体系结构和编译器,任何类型的最大对齐都是常量,通常它是所有基本类型的最大对齐。但是,对象的大小应该是其对齐的倍数。有时,必须通过向对象内的值添加填充来满足此要求。
如果您的编译器足够现代,它将支持_Alignof
,类似于sizeof
,因此您可以使用小程序检查实际对齐情况。我认为在你的架构上最大对齐是4.如果malloc
总是返回8对齐的地址,那么它仍然符合。 malloc
符合类型最大对齐倍数的对齐并不罕见。
答案 4 :(得分:0)
你错过了,虽然类型的大小必须是其对齐的倍数(受实际硬件限制),但它们不必相等。
如果是long double
,则转换为
_Alignof (long double) == 4
sizeof (long double) == 12
使用gcc / x86和
_Alignof (long double) == 16
sizeof (long double) == 16
使用gcc / x64,在这两种情况下long double
都具有80位扩展精度。
如果我们不受约束的限制,我们最自然会最终得到
sizeof (long double) == 10
在存在对齐的情况下,我们要么必须使用2的对齐(我们不是出于效率原因),要么将填充引入数组,以便元素正确对齐。这违反了C语言的语义,数组的大小是其元素大小和计数的乘积。