阵列方向结构

时间:2011-11-24 08:44:02

标签: c unions

对于下面的工会声明

union a
{
    int i;
    char ch[2];
};
union a u;
u.ch[0] = 3;
u.ch[1] = 2;

由于ich存储在同一位置,i现在应该<binary rep. of 3><binary rep. of 2>连接。但是,它以相反的顺序存储。

printf("%d",i);

给出515。 为什么呢?

3 个答案:

答案 0 :(得分:3)

因为您正在打印数字%d。所以,你有:

u.ch[0] = 3;

二进制是

0000 0011  // 8bits, as char is 1B

然后你有

u.ch[1] = 2;

0000 0010 // 8bits, as char is 1B

并且“当你把2和2放在一起时”(:D)

  00..00                   0000 0010          0000 0011 // sizeof (int) * 8 bits
  ^^^^^^                   ^^^^^^^^^          ^^^^^^^^^
//(sizeof(int)*8-16)bits   this is the 2    this is the 3

在十进制中为515


对不起,我错过了“为什么”的部分。它是特定于平台的,你应该阅读Endianness并且更具体 - 关于Big-endian和Little-endian。文章中有一些例子。 提示:好像你有一台小端机器

好的,我在这里总结一下我的评论:数组保证存储在连续的内存中。 我们假设sizeof( int ) == 2,以便于解释。所以,你有

u.ch[0] = 3;
u.ch[1] = 2;

这将首先存储3,并在下一个字节中写入2。所以,正如你(我猜)所期望的那样,记忆是:

0000 0011 0000 0010
^^^^3^^^^ ^^^^2^^^^

但请记住你使用union!然后打印int。所以,int具有相同的位:

0000 0011 0000 0010

你的机器是小端,将其“翻译”为:

0000 0010 0000 0011 (reversed order of the bytes!)

哪个是515

的二进制表示

答案 1 :(得分:2)

结果取决于您正在尝试编程的计算机的endianness

在小型终端机器Intel i686上是515

$ uname -m
i686
$ ./a.out
515

并且在像Sparc这样的bin端机器上是770

$ uname -m
sun4v
$ ./a.out
770

这是因为endianess将确定ch[0]是高阶字节(大端)还是低阶字节(小端)i

答案 2 :(得分:0)

它给出了515,因为这是未指定的行为。没有人知道你正在使用什么编译器,以及编译器如何处理联合,没有人能回答你的问题。

  • 编译器可以在联合内的任何位置自由存储任意数量的填充字节,但第一个字节除外。

  • 该程序只需要返回与上次访问联合相对应的结果。如果您通过char数组成员进行访问,则只保证对char数组的读访问权是可靠的。读int成员可以给你任何东西,你不知道是什么。

  • 由于这是未指定的行为,编译器甚至不需要记录它将如何处理此类访问。如果你很幸运他们做到了。

  • 编译器完全可以为这样的代码提供填充字节或垃圾值。