今天我了解到,如果你声明一个 char 变量(即 1 个字节),汇编器实际上在内存中使用 4 个字节,因此边界位于字长的倍数上。
如果一个 char 变量无论如何都使用 4 个字节,那么将其声明为 char 有什么意义?为什么不将其声明为 int?他们不使用相同数量的内存吗?
当您用汇编语言编写并为一个字符声明空间时,汇编器为一个字符分配空间,仅此而已。(我写的是关于通用汇编器的。)如果你想在汇编语言中对齐对象,你必须为此目的包含汇编器指令。
当您使用 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
之后,它是一个与八个字节的倍数对齐的八字节对象。a
放置限制最少的对象:为、b
和分别留出一个字节c
。这种重新排序避免了浪费空间,任何体面的编译器都会将它用于可以自由排列的内存(例如堆栈上的自动对象或全局内存中的静态对象)。
当您在结构中声明成员时,编译器需要使用您声明成员的顺序,因此它无法执行此重新排序以节省空间。在这种情况下,声明字符对象和其他对象的混合可能会浪费空间。
问:程序是否为您声明的每个“char”分配四个字节?
答:不 - 绝对不是 ;)
问:是否有可能,如果您分配一个字节,程序可能会“填充”额外的字节?
答:是的——绝对是的。
问题是“对齐”。一些计算机体系结构必须访问相对于特定偏移量的数据值:16 位、32 位等。如果它们总是访问相对于偏移量的字节,则其他体系结构的性能会更好。因此“填充”:
其他人大部分都回答了这个问题。假设一个 char 是一个单字节,声明一个 char 是否意味着它总是填充到对齐?不,有些编译器在默认情况下会做一些不做的事情,而且很多你可以在某处使用某种命令来更改默认值。这是否意味着您不应该使用字符?这取决于,首先填充并不总是发生,所以少数浪费的字节并不总是发生。您正在使用编译器使用高级语言进行编程,所以如果您认为整个二进制文件中只有 3 个浪费的字节......再想一想。根据使用 chars 的体系结构可以节省一些,例如在某些体系结构上加载立即数可以节省三个字节或更多。其他架构只是为了对寄存器进行简单操作,需要额外指令来对较大的寄存器进行签名扩展或剪辑,以使其表现得像一个字节大小的寄存器。如果您使用的是 32 位计算机并且使用 8 位字符,因为您只从 1 数到 100,您可能想要使用全尺寸的 int,从长远来看,您可能不会通过使用字符。现在,如果这是一台运行 DOS 的基于 8086 的 PC,那就另当别论了。或者一个 8 位微控制器,那么你想尽可能地倾向于 8 位变量。现在,如果这是一台运行 DOS 的基于 8086 的 PC,那就另当别论了。或者一个 8 位微控制器,那么你想尽可能地倾向于 8 位变量。现在,如果这是一台运行 DOS 的基于 8086 的 PC,那就另当别论了。或者一个 8 位微控制器,那么你想尽可能地倾向于 8 位变量。
声明单个char
变量可能确实没有任何意义。
然而,可能有很多充分的理由需要char
-array ,而-arrayint
真的不能解决问题!
(尝试用整数填充数据结构......)