2012-05-30 61 views
3

我无法理解联盟如何运作..混淆联盟用C

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    union { 
    int a:4; 
    char b[4]; 
    }abc; 
abc.a = 0xF; 

    printf(" %d, %d, %d, %d, %d, %d\n", sizeof(abc), abc.a, abc.b[0], abc.b[1], abc.b[2], abc.b[3]); 

    return 0; 
} 

enter image description here
在上面的程序。
我制作int a : 4;
所以,一个应该采取4位。
我现在存储,a = 0xF; //i.e a= 1111(Binary form)
所以,当我访问b[0 0r 1 or 2 or 3]为什么输出不来像1, 1, 1, 1

+1

实际上,在你分配到'abc.a'之后访问'abc.b'是我所知的未定义的行为。你不应该以任何可能认为它可行的方式依赖它。 –

+1

@NiklasB。不再有C11可用,它在那里定义。 –

+0

@Daniel Fischer:很好,谢谢。 –

回答

3

您的工会的总大小将至少为4 * sizeof(char)

假设你正在使用手柄编译器这个定义的行为,考虑以下因素:

  1. abc永远不会完全初始化,所以它包含零和一的随机分类。大问题。那么,这样做第一:
    memset(&abc, 0, sizeof(abc));
  2. 工会应该是它最大成员的大小,所以你现在应该有4归零出字节00000000 00000000 00000000 00000000
  3. 你只设置4 高,所以你的工会会变成这样:
    00000000 00000000 00000000 00001111
    11110000 00000000 00000000 00000000

    我不知道你的编译器如何处理这种类型的对齐,所以这是我能做的最好的。

你也可以考虑做一个char对位的转换,所以你可以手动检查每个二进制格式的价值和每一位:
Access individual bits in a char c++

祝您好运!

0

因为每个char需要(在大多数平台上),1个字节,即8位,所以所有的a 4位属于b[]的单个元素。

这旁边,它是编译器相关的位字段的存储方式,所以它没有定义,在其中的b[]映射字节......

2

0xF是-1,如果你把它看成一个4位有符号,所以输出是正常的。 b甚至没有完全分配,所以它的值是未定义的。它是一个4字节的实体,但你只能分配一个4位的实体。所以一切看起来都很正常。