1

我这里有一些代码使用位集将许多 1 位值存储到一个字符中。

基本上

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,因为设置了其他位。我想知道这是否是正确的行为,或者我的编译器是否损坏。该编译器是一种嵌入式编译器,可为飞思卡尔 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包含1or b00000010

4

4 回答 4

0

我认为您不能将 1 位char设置为 1。剩下一位来确定它是否已签名,因此您最终会得到0and之间的区别-1

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

于 2012-07-03T16:03:03.440 回答
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
  }
}

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

C99 上一个公开可用的草稿中的一些阅读材料

第 6.7.2.1 段

4 位域的类型应为 _Bool、signed int、unsigned int 或其他一些实现定义的类型的合格或不合格版本。

(对我而言,这意味着编译器至少应该正确处理您的第二个示例)和

9 位域被解释为由指定位数组成的有符号或无符号整数类型。107) 如果值 0 或 1 存储到 _Bool 类型的非零宽度位域中,则位域的值字段应与存储的值进行比较。

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

于 2012-07-03T16:27:27.263 回答
0

如果 Bool 类型定义为 unsigned int 或类似类型,或者您的编译器不支持打包枚举,我可以理解为什么您可能想要使用 char 来存储标志。您可以使用宏设置一些“标志”(我在下面将它们命名为它们的位置值,但按照它们的含义命名它们更有意义)如果 8 个标志还不够,这可以扩展到其他类型,直到 sizeof(类型)* 8 个标志。

/* 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));
}
于 2012-07-04T06:19:59.237 回答
0

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

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

func((char)bits._8));

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

于 2012-07-04T14:32:15.533 回答