C问题:为什么char实际占用内存中的4个字节?

Boo*_*ean 4 c size struct char data-structures

我写了一个小程序来检查我的内存中char占用了多少字节,它显示char实际占用内存中的4个字节.我理解这主要是因为字对齐,并没有看到char只有1个字节的优点.为什么不使用4个字节的char?

int main(void)
{
  int a;
  char b;
  int c;
  a = 0;
  b = 'b';
  c = 1;
  printf("%p\n",&a);
  printf("%p\n",&b);
  printf("%p\n",&c);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:0x7fff91a15c58 0x7fff91a15c5f 0x7fff91a15c54

更新:我不相信malloc只会为char分配1个字节,即使sizeof(char)作为参数传递,因为malloc包含一个头将确保头是字对齐的.任何意见?

Update2:如果要求你有效地使用没有填充的内存,唯一的方法是创建一个特殊的内存分配器?或者是否可以禁用填充?

Ric*_*iwi 6

你有int,char,int

请参阅"为什么限制字节对齐?"下的图像. http://www.eventhelix.com/realtimemantra/ByteAlignmentAndOrdering.htm

          Byte 0 Byte 1 Byte 2  Byte 3
0x1000               
0x1004  X0     X1     X2      X3
0x1008               
0x100C         Y0     Y1      Y2
Run Code Online (Sandbox Code Playgroud)

如果它以4字节,1字节和4字节形式存储它们,则需要2个cpu周期来检索int c并进行一些位移以使c的实际值正​​确对齐以用作int.


Jef*_*eff 6

对准

让我们看看你输出的打印a,b和c的地址:

输出:0x7fff91a15c58 0x7fff91a15c5f 0x7fff91a15c54

请注意,b不在同一个4字节边界上?并且a和c彼此相邻?这是它在内存中的样子,每行占用4个字节,最右边的列占第0位:

| b | x | x | x | 0x5c5c
-----------------
| a | a | a | a | 0x5c58 
-----------------
| c | c | c | c | 0x5c54 
Run Code Online (Sandbox Code Playgroud)

这是编译器优化空间和保持字对齐的方式.即使你的b地址是0x5c5f,它实际上并没有占用4个字节.如果您使用相同的代码并添加短d,您将看到:

| b | x | d | d | 0x5c5c
-----------------
| a | a | a | a | 0x5c58 
-----------------
| c | c | c | c | 0x5c54 
Run Code Online (Sandbox Code Playgroud)

其中d的地址是0x5c5c.短路将与两个字节对齐,因此在c和d之间仍然会有一个未使用的内存字节.添加另一个字符,你会得到:

| b | e | d | d | 0x5c5c
-----------------
| a | a | a | a | 0x5c58 
-----------------
| c | c | c | c | 0x5c54 
Run Code Online (Sandbox Code Playgroud)

这是我的代码和输出.请注意,我的地址会略有不同,但它是我们真正关心的地址中最不重要的数字:

int main(void)
{
  int a;
  char b;
  int c;
  short d;
  char e;
  a = 0;
  b = 'b';
  c = 1;
  printf("%p\n",&a);
  printf("%p\n",&b);
  printf("%p\n",&c);
  printf("%p\n",&d);
  printf("%p\n",&e);
  return 0;
}

$ ./a.out 
0xbfa0bde8
0xbfa0bdef
0xbfa0bde4
0xbfa0bdec
0xbfa0bdee
Run Code Online (Sandbox Code Playgroud)

的malloc

malloc的手册页说它" 分配大小字节并返回指向已分配内存的指针 ".它还说它将" 返回指向已分配内存的指针,该内存适合任何类型的变量 ".从我的测试开始,对malloc(1)的重复调用以"双字"增量返回地址,但我不会指望这一点.

注意事项

我的代码是在x86 32位机器上运行的.其他机器可能略有不同,有些编译器可能会以不同的方式进行优化,但这些想法应该成立.


Ale*_*kiy 5

变量本身不占用4个字节的内存,它占用1个字节,然后是3个字节的填充,因为堆栈上的下一个变量是一个int,因此必须是字对齐的.

在类似下面的情况下,您会发现变量的地址anotherChar比1的大1个字节b.然后在int之前跟随2个字节的填充c

int main(void)
{
  int a;
  char b;
  char anotherChar;
  int c;
  a = 0;
  b = 'b';
  c = 1;
  printf("%p\n",&a);
  printf("%p\n",&b);
  printf("%p\n",&anotherChar);
  printf("%p\n",&c);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)