汇编和字对齐

时间:2012-09-06 15:48:59

标签: c assembly

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

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

4 个答案:

答案 0 :(得分:4)

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

当您使用C编写,并且编译器将其转换为程序集和/或机器代码时,可以填充字符的空间。通常这不是因为角色对象的对齐优势,而是因为你在程序中声明了几件事。例如,考虑一下声明:

时会发生什么
char a;
char b;
int i;
char c;
double d;

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

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

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

更智能的编译器将执行此操作:

  • 根据对齐要求对其拥有的对象进行排序以分配空间。
  • 首先放置限制性最强的对象:为d预留八个字节。
  • 放置下一个限制性最强的对象:为i留出四个字节。请注意,i与四个字节的倍数对齐,因为它跟随d,这是一个8字节的对象,与8个字节的倍数对齐。
  • 放置限制最少的对象:为abc分别留出一个字节。

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

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

答案 1 :(得分:3)

问:程序是否为您声明的每个“char”分配了四个字节?

答:不 - 绝对没有;)

问:如果你分配一个字节,程序可能会“填充”额外的字节吗?

<答>答:是的 - 绝对是的。

问题是“对齐”。某些计算机体系结构必须访问特定偏移量的数据值:16位,32位等。如果其他体系结构执行更好,如果它们总是访问一个字节相对于抵消。因此“填充”:

答案 2 :(得分:0)

声明单个char变量确实没有任何意义。

但是,有一个很好的理由需要一个char - 数组,其中一个int - 数组实际上不会这样做!

(尝试使用整数填充数据结构......)

答案 3 :(得分:0)

其他人在很大程度上回答了这个问题。假设char是一个字节,声明一个char意味着它总是填充到一个对齐?不,有些编译器在默认情况下做了一些,而且很多你可以在某处使用某种命令来改变默认值。这是否意味着你不应该使用char?这取决于,首先填充不总是发生,所以几个浪费的字节不总是发生。您正在使用编译器以高级语言进行编程,因此如果您认为整个二进制文件中只有3个浪费的字节,那么请再想一想。根据使用字符的体系结构可以节省一些成本,例如加载即时节点可以在某些体系结构上节省三个字节或更多字节。其他架构只是为了使用寄存器额外指令进行简单操作,需要对较大寄存器进行符号扩展或限幅,使其行为类似于字节大小的寄存器。如果您使用的是32位计算机并且使用的是8位字符,因为您的计数从1到100,那么您可能需要使用全尺寸的int,从长远来看,您可能无法通过使用焦炭。现在,如果这是一台基于8086的pc运行dos,那就是另一回事了。或者是一个8位微控制器,那么你想尽可能地倾向于8位变量。