我这里有一些代码,它使用位集将许多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
?
答案 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));
其他答案对于正确的行为是正确的。我仍然将这一个标记为答案,因为它是我问题的答案。