汇编程序和字对齐

i l*_*low 2 c assembly

今天我了解到,如果你声明一个 char 变量(它是 1 个字节),汇编器实际上在内存中使用了 4 个字节,因此边界位于字大小的倍数上。

如果 char 变量无论如何都使用 4 个字节,那么将其声明为 char 有什么意义?为什么不将其声明为 int?他们不是使用相同数量的内存吗?

Eri*_*hil 5

当您使用汇编语言编写并为一个字符声明空间时,汇编程序会为一个字符分配空间,而不会再分配空间。(我写的是关于常见的汇编程序。)如果要在汇编语言中对齐对象,则必须为此目的包含汇编程序指令。

当您用 C 编写并且编译器将其转换为汇编和/或机器代码时,可能会填充字符的空间。通常这样做不是因为字符对象的对齐优势,而是因为您在程序中声明了一些东西。例如,考虑当您声明时会发生什么:

char a;
char b;
int i;
char c;
double d;
Run Code Online (Sandbox Code Playgroud)

一个天真的编译器可能会这样做:

  • a在相关内存的开头分配一个字节,它恰好与 16 个字节的倍数对齐。
  • 为 分配下一个字节b
  • 然后它想放置int i需要四个字节的 。在这台机器上,int对象必须对齐到四个字节的倍数,否则试图访问它们的程序将崩溃。因此编译器跳过两个字节,然后为i.
  • 为 分配下一个字节c
  • 跳过七个字节,然后为 留出八个字节d。这使得d对齐到 8 个字节的倍数,这对这个假设的机器是有益的。

因此,即使使用简单的编译器,字符对象本身也不需要四个完整的字节。它可以与相邻角色对象或其他不需要更大对齐的对象共享。但是会浪费一些空间。

一个更聪明的编译器会这样做:

  • 根据对齐要求对必须为其分配空间的对象进行排序。
  • 首先放置最严格的对象:为 留出八个字节d
  • 放置下一个最严格的对象:为 留出四个字节i。请注意,i它与四字节的倍数对齐,因为它跟在 之后d,这是一个八字节的对象,与八字节的倍数对齐。
  • 将限制最少的对象:抛开一个字节的每一个abc

这种重新排序避免了浪费空间,任何体面的编译器都会将它用于可以自由安排的内存(例如堆栈上的自动对象或全局内存中的静态对象)。

当您在结构中声明成员时,编译器需要使用您声明成员的顺序,因此它无法执行这种重新排序以节省空间。在这种情况下,声明角色对象和其他对象的混合可能会浪费空间。