2017-04-17 129 views
-1
struct st 
{ 
    int a1 : 3; 
    int a2 : 2; 
    int a3 : 1; 
} 

void main(void) 
{ 
    x.a3 = -1; 

    if (x.a3 == -1) printf("TRUE\n"); 
    else printf("FALSE\n"); 

    x.a3 = 1; 
    if (x.a3 == 1) printf("TRUE\n"); 
    else printf("FALSE\n"); 
} 

如果'x.a3 = -1;'首先如果是TRUE
但是,为什么'x.a3 = 1'不会在第二个变化?它仍然是x.a3 = -1。结构变量未被赋值改变

and
如果我输入'x.a3 = 1;'在第一个如果,它仍然x.a3 = = 1!它并没有改变!

Debug Result in XCode

+0

'void main()'是一个无效的签名。最小签名是'int main(void)'。什么是'x'?代码不能编译。提供[mcve]。 – Olaf

+0

@Olaf在阅读C11 5.1.2.2.1 2时,“它应该用int的返回类型或其他实现定义的方式来定义。” 'void main(void)'是实现定义的,如果它是有效的,当然不是无效的。我想这取决于“或”。 IAC,当然不是OP的关键问题。 – chux

+0

@chux:这是受解释。除此之外,所有的全尺寸操作系统都需要一个“int”结果。 – Olaf

回答

3

的问题是,一个签署1位变量只能容纳两个值,-10(阅读Two's complement)。仅保留1(准确地说+ 1)是不够的。

为了详细描述,而写分配

x.a3 = 1; 

整数的常数1的值被存储到用于构件a3保留的存储器位置,但在访问变量,按照变量的符号性(可能是signedunsigned,按照章节§6.7.2/ P5的实现定义的行为),表示将从内存中读取。

在二的补一存储值的1的表示,将产生的结果-1(根据MSB值),所以与== 1条件检查会失败,始终。

+1

它是实现定义是否在位字段中的纯'int'是一个有符号或无符号的值。事实上,几乎所有关于位域的内容都是实现定义的。 –

+0

@chux感谢您纠正我,我错过了之前的评论。更新。 –

0

由于字段a3是1位int(因此是带符号的),它只能保存0(如果该位为0)或-1(如果该位是符号位为1) 。因此,当您尝试分配值1时,将存储该值的表示形式,并且该给定数据类型中的表示形式为-1。

仅仅因为1位int中的值-1与1位unsigned int中的值1具有相同的表示,并不意味着它们与相同的事情相比较。

0
int a3 : 1; 

是一个带位字段的结构,它定义了要使用多少空间来存储var。您正在使a1成为一个带符号的int整数,它只能保存值-1和0.如果您希望a3保存值1,那么您可能希望的语法是int a3 = 1,然后是多种方法之一这样做可能看起来像这样

struct st 
{ 
    int a1 : 3; 
    int a2 : 2; 
    int a3 : 1; 
}; 


void main(void) 
{ 
    struct st x = {1,2,3}; 
    x.a3 = -1; 

    if (x.a3 == -1) printf("TRUE\n"); 
    else printf("FALSE\n"); 

    x.a3 = 1; 
    if (x.a3 == 1) printf("TRUE\n"); 
    else printf("FALSE\n"); 
}