“对齐指针”是什么意思?

51

请问什么是对齐指针

6个回答

53

这意味着指向的地址能被某个因子整除。

有时候会用到术语“自然对齐”,通常指需要将具有自然对齐属性的对象放置在其大小所能整除的地址上。

对齐有时非常重要,因为许多硬件相关的东西会对这种对齐施加限制。

例如,在经典的SPARC 架构(以及经典的ARM 架构,我想是)中,你无法从奇数地址读取大于一个字节的整数。试图这样做将立即使程序停止并报告总线错误。在 x86 架构中,CPU 硬件会处理这个问题(通过根据需要进行多次访问来访问缓存或内存),尽管可能会花费更长的时间。类似 RISC 的架构通常不会为你处理这些问题。

这些事情也可能会影响填充,例如在结构体字段之间插入虚拟数据以维持对齐。一个像这样的结构体:

struct example
{
  char initial;
  double coolness;
};

很可能会在字段之间有7个字节填充,以使 double 字段对其偏移量可整除自身大小(我假设为8)。

当以二进制方式查看时,对齐到n字节的地址将其log2(n)最低有效位设置为零。例如,需要32字节对齐的对象将具有正确对齐的地址,该地址以(二进制)00000结尾,因为log2(32)为5。这也意味着可以通过清除所需数量的位来强制地址对齐。


@unwind:OOC,你知道有任何实现把那个因数设置为奇数的吗? - SiegeX
2
“aligned to n bytes” 应该翻译为“按 n 对齐”,因为 log2(1) = 0。你的意思是 log2(8) = 3。 - Alex Budovski
@Axel:我没有理解... 是的,log2(1)是0,需要1字节对齐的对象不需要强制将任何LSB清零。我添加了一个示例,希望这样更清楚。你还是认为它是错误的吗? - unwind
1
请注意,对齐并不总是保证的。例如,struct X { char a; example b; }; 这就是为什么在需要对齐时很难保证它的对齐性,并且为什么在这种情况下通常需要显式使用对齐 malloc 函数来保证其对齐性。 - tenfour
1
@tenfour:实际上,“coolness”将被对齐。编译器将为“struct example”提供与所有成员兼容的对齐要求。假设“double”是8字节对齐的,这意味着“struct example”也是8字节对齐的。因此,“sizeof(X)==24”,在“a”和“b”之间还有另外7个字节的填充。反过来,“X”继承了相同的8字节对齐要求。 - MSalters

6

补充一下unwind所说的,这是我最近在一个任务中使用的struct:

struct infosale {               
    int   noseq;                
    char  salesman[30];         
    char  product[11];          
    int   count;                
};                               

您可能期望这个struct的大小为(4+30+11+4=)49字节,但实际上与sizeof相比为52。因为noseq4字节+ salesman32字节(对齐)+ product12字节(对齐),而count4字节,因此总共是52字节。

1
你的数学有误。而且,我不确定填充是否被分割,而不是直接在最后一个“int”之前添加3个必要字节的填充。 - Deduplicator
1
我已经用GCC进行了测试(不记得版本号),使用C语言,这是调试器在那个时候报告的结果。我需要回顾一下才能确认。但我非常确定编译器不喜欢奇地址,并且会将变量对齐到偶数偏移量;所以它会填充空白,除非明确指示不要这样做。(我已经有一段时间没有写C代码了!) - Yanick Rochon
1
@Deduplicator:实际上,对于编译器而言,为大型char数组成员提供与动态分配的char数组相同的对齐保证并不是那么不寻常(也就是说,对于任何适合的原始数据类型,对齐都足够好)。 - Ben Voigt
1
@Deduplicator:好的,s/unusual/unreasonable/。 - Ben Voigt
1
你所写的似乎是错误的。应该是:noseq为4 + salesman为30 + product为11 + 填充到int(在这种情况下为3)+ count为4,因此结果为52字节。 - user1723095
显示剩余8条评论

4
根据上下文,它可能是指指针本身被对齐,或者指针所指向的内容被对齐。
“对齐”意味着某个对象存储在一个地址上,该地址是某个常数的倍数。例如,对于32位整数,这几乎总是4。这是因为一个字节是8位:4 * 8 = 32位。如果对象存储在对齐的地址上,处理器通常可以更快地访问内存,或者对于某些处理器来说,无法进行非对齐访问。

1

它是指向“对齐”地址的指针。对齐是指地址是某个值的倍数,通常是所指向的东西(如果是原始类型)的大小,或者需要这种对齐的某些数据成员的大小。

通常情况下,您无需担心这一点;内存分配函数将确保它们提供给您的内存被正确对齐。只有在开始使用指针转换来进行不安全操作时,您才开始担心对齐问题。


0

正如其他人之前提到的,这意味着您的指针可以被某个字节数均匀地整除。

要检查指针是否对齐,您可以执行以下操作:

isaligned = !( (long)pointer % bytes );

现在,“isaligned”为真,如果“pointer”对“bytes”字节进行了对齐。

实际上,你是做不到的,而且你的编译器会告诉你这一点。你可以尝试使用bool isAligned = ((reinterpret_cast<size_t>(pointer) % sizeof(*pointer)) == 0); - MSalters
没错。你无法对指针执行模运算,所以你必须将其转换为更合适的类型。我来修复! - onemasse

-1

对齐指针是指可以通过添加常量及其倍数来访问相邻内存位置的指针。

例如:char a[5] = "12345";

这里,如果您每次将字符大小与a相加,则a是一个常量指针,您可以访问下一个字符,即:

a+sizeofchar 将访问2

a+( sizeofchar*2 ) 将访问3等等

同样地,如果您按位访问变量值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接