将位字段成员分配给char

时间:2012-07-03 15:12:14

标签: c

我这里有一些代码,它使用位集将许多1位值存储到char中。

基本上

struct BITS_8 {
  char _1:1;
  (...)
  char _8:1;
}

现在我试图将其中一个位作为参数传递给函数

void func(char bit){
  if(bit){
    // do something
  }else{
    // do something else
  }
}

// and the call was
struct BITS_8 bits;
// all bits were set to 0 before
bits._7 = 1;
bits._8 = 0;
func(bits._8);

解决方法是在调用函数时将该单位取出:

func(bits._8 & 0x80);

但我继续进入//do something,因为其他位已设置。我想知道这是正确的行为还是我的编译器坏了。编译器是一个嵌入式编译器,可为freescale ASIC生成代码。

编辑:2个错误:传递参数并且bits._8应该为0,否则错误就没有意义。

澄清

我对标准对作业的说法感兴趣

struct X{
   unsigned int k:6;
   unsigned int y:1;
   unsigned int z:1;
}

X x;
x.k = 0;
x.y = 1;
x.z = 0;

char t = X.y;

现在t应该包含1还是b00000010

4 个答案:

答案 0 :(得分:0)

我不认为你可以将1位 char 设置为1.还有一位用于确定它是否已签名,所以你最终0-1之间存在差异。

你想要的是unsigned char,以隐藏这个签名位。然后你可以使用1和0。

答案 1 :(得分:0)

这些年来,我对这些特定的编译器有点怀疑,通常他们对可以描述的C标准细节的解释并不是很好。在这些情况下,更务实的方法可以帮助您避免精神错乱,并完成工作。在这种情况下,这意味着,如果编译器没有合理的行为(你可以定义为与gcc完全不同的行为),你可以稍微帮助它。

例如,您可以将func修改为:

void func(char bit){
  if(bit & 1){ // mask off everything that's none of its business
    // do something
  }else{
    // do something else
  }
}

并且你的插件问题:t应该包含1.它不能包含10个二进制文件,因为变量只有1位宽。

last publicly available draft for C99

中的一些阅读材料

第6.7.2.1段

  

4位字段应具有合格或不合格的类型   _Bool的版本,signed int,unsigned int或其他   实现定义的类型。

(这对我来说意味着编译器至少应该正确处理你的第二个例子)和

  

9位字段被解释为有符号或无符号整数类型   由指定的位数组成.107)如果值为0或1   存储在类型的非零宽度位域中   _Bool,位字段的值应该等于存储的值。

由于您的编译器是用于嵌入式使用的,其中位域是一个相当重要的特性,我希望它们的实现是正确的 - 如果它们声称已经实现了位域。

答案 2 :(得分:0)

我可以看到为什么你可能想要使用char来存储标志,如果Bool是对unsigned int或类似的类型,或者你的编译器不支持打包的枚举。您可以使用宏设置一些“标志”(我将它们命名为下面的位置值,但是将它们命名为它们的含义更有意义)如果8个标志不够,则可以扩展到其他类型的大小( type)* 8 flag。

/* if you cannot use a packed enum, you can try these macros 
 * in combination with bit operations on the "flags"
 * example printf output is: 1,1,6,4,1 
 * hopefully the example doesn't make it more confusing
 * if so see fvu's example */

#include <stdio.h> /* for printf */
#define ONE ((char) 1)
#define TWO (((char) 1)<<1)
#define FOUR (((char) 1)<<2)
#define EIGHT (((char) 1)<<3)
#define SIXTEEN (((char) 1)<<4)
#define THIRTYTWO (((char) 1)<<5)
#define SIXTYFOUR (((char) 1)<<6)
#define ONETWENTYEIGHT (((char) 1)<<7)

int main(void){
printf("%d,%d,%d,%d,%d\n",ONE & ONE, ONE | ONE, TWO | 6, FOUR & 6, sizeof(ONE));
}

答案 3 :(得分:0)

好的,这是一个编译错误。我写了生产编译器的人,他们证实了这一点。只有在具有内联函数的位域时才会发生这种情况。

他们推荐的解决方案是(如果我不想等待补丁)

func((char)bits._8));

其他答案对于正确的行为是正确的。我仍然将这一个标记为答案,因为它是我问题的答案。