如何在C语言中检查内存地址是否为32位对齐

24

我的问题分为两个部分。

首先,作为这个地址空间的新手,我想知道地址的内存对齐是什么意思。我在谷歌上搜索了一下,但我也想在这里问这个问题,因为我发现这里的答案非常有用。

我的问题的第二部分与对齐和编程有关:我如何确定一个地址是否按4字节对齐?我在某个地方读到:

  if(address & 0x3) // for 32 bit register 

但是我不太明白这个是如何检查4字节对齐的。是否有人可以详细解释一下?

编辑:如果有人可以画出图像来说明这个问题就太好了。

谢谢。

1个回答

41

顺序地址是指内存中连续的字节。

“4字节对齐”的地址是4字节的倍数。换句话说,地址的二进制表示以两个零结尾(00),因为在二进制中它是二进制值4100b)的倍数。因此,检测4字节对齐的地址为:

if ( (address & 0x3) == 0 )
{
    // The address is 4-byte aligned here
}

或者简单地说

if ( !(address & 0x3) )
{
    // The address is 4-byte aligned here
}

0x3 是二进制的 11,或者说是地址的最低两位的掩码。

对齐很重要,因为如果数据项的地址对齐,一些CPU操作会更快。这是因为CPU是基于32位或64位字的。少量数据(例如4字节)如果按照4字节对齐,则可以很好地适应32位字。如果没有对齐,则可能跨越32位边界并需要额外的内存获取。现代CPU还有其他优化,可提高对齐数据的性能。

这里有关于对齐和速度的样例文章。

这里有一些关于对齐的示意图


2
有些设计(例如ARM)不仅在非对齐访问方面效率低下,而且甚至在硬件上也不支持它 - 程序员必须显式地读取这些部分并将它们重新组合。不用说,在那里应避免使用非对齐的数据,除非为了尺寸调整或以需要它的格式进行交换。 - Chris Stratton
1
@mbratch,针对上述情况,如果地址不是4字节对齐的,是否有可能访问到不需要的寄存器? - Amit Singh Tomar
看@nos。我的观点非常简单,如果我有一个FPGA设备,它有3个寄存器,每个寄存器都是32位大小,第1个寄存器的地址将是0x0,第2个寄存器的地址将是0x4,第3个寄存器的地址将是0x8。现在,如果我有一个例程,它将读取这些寄存器,如果我提供的地址不是4字节对齐的地址,那么读取所需的寄存器将失败。有人同意我的想法吗? - Amit Singh Tomar
1
有时您可能希望以宏形式甚至以更适用于所有翻译单元或源的形式来使用它,在此处的StackOverflow链接中,您可以获得一些宏。https://dev59.com/cXI-5IYBdhLWcg3wW28L - Peter
1
你太棒了!那些介绍的链接真的很棒!我终于明白了对齐。非常感谢你。 - Sam
显示剩余4条评论

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