2012-09-06 85 views
1

今天我了解到,如果声明一个字符变量(它是1个字节),汇编程序实际上在内存中使用4个字节,以便边界位于字大小的倍数上。汇编程序和字对齐

如果一个char变量使用4个字节,那么声明它为char是什么意思?为什么不把它声明为int?难道他们不使用相同数量的内存?

+1

你试过一个字符数组吗? – Nemo

+3

以字节为单位的转换取决于您的编译器。在一个平台上,它可以是你所说的,但在另一个平台上它可以有不同的东西。 – Bgi

回答

4

当你用汇编语言编写,并为角色声明空间,汇编一个字符,没有更多的分配空间。 (我写的是关于通用汇编程序的。)如果要用汇编语言对齐对象,则必须包含用于此目的的汇编程序指令。

在C中编写代码时,编译器将其转换为汇编代码和/或机器代码时,可能会填充字符的空间。通常这不是因为字符对象的对齐优势而完成的,而是因为您在程序中声明了几件事情。例如,考虑当你声明会发生什么:

char a; 
char b; 
int i; 
char c; 
double d; 

一个天真的编译器可能做到这一点:

  • 在相关记忆,这恰好是对齐到年初分配为a一个字节多个,比如16个字节。
  • b分配下一个字节。
  • 然后它想要放置需要四个字节的int i。在这台机器上,int对象必须对齐到四个字节的倍数,否则试图访问它们的程序将崩溃。所以编译器跳过两个字节,然后为i留出四个字节。
  • c分配下一个字节。
  • 跳过7个字节,然后为d预留8个字节。这使得d对齐八个字节的倍数,这对这个假设的机器是有益的。

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

一个聪明的编译器会做到这一点:

  • 排序它必须根据自己的对齐要求分配空间的对象。
  • 首先放置限制性最强的对象:为d预留8个字节。
  • 放置下一个最受限制的对象:为i预留四个字节。请注意,i与四个字节的倍数对齐,因为它跟随d,这是一个八字节对象,与八个字节的倍数对齐。
  • 放置限制最少的对象:为a,bc预留一个字节。

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

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

0

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

可能不过是想char许多很好的理由 - 阵列,其中一个int - 阵列真的不会做的伎俩!

(尝试填补与整型数据结构...)

+0

如果使用char数组,每个char是否只使用1个字节? –

+1

@badatmath:这的确是'char'的定义。 –

+1

试试看看。 –

3

问:计划分配为每一个“字符”四个字节声明?

答:不 - 绝对不是;)

问:有没有可能,如果你分配一个字节,程序可能“垫”以额外的字节?答:是的 - 绝对是的。

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

0

其他人大部分都回答了这个问题。假设一个字符是一个字节,是否声明一个字符意味着它总是贴着对齐?不,有些编译器在默认情况下会做某些操作,很多可以在某处使用某种命令来更改默认值。这是否意味着你不应该使用char?这取决于,首先填充并不总是发生,所以少量浪费的字节不会总是发生。你正在使用编译器以高级语言进行编程,所以如果你认为你的整个二进制文件只有3个浪费的字节......再想一想。根据体系结构使用字符可以节省一些成本,例如,加载立即数可以在某些体系结构中节省三个字节或更多。其他体系结构只需要使用寄存器附加指令执行简单操作就需要对较大的寄存器进行签名扩展或剪切,以表现得像一个字节大小的寄存器。如果你使用的是32位计算机,并且你使用的是8位字符,因为你只计数从1到100,那么你可能想要使用一个完整大小的int,从长远来看,你可能没有使用焦炭。现在如果这是一个基于8086的PC运行dos,那是一个不同的故事。或者一个8位微控制器,那么你想尽可能地倾向于8位变量。