【问题标题】:Value of integer bit field is alternately equal to 0 or 1 when bit field width is less than the needed当位域宽度小于需要时,整数位域的值交替等于 0 或 1
【发布时间】:2017-03-02 12:59:36
【问题描述】:

我正在测试 C 中的代码,其中我有意在结构内定义一个整数位字段(variable not_enough),宽度为 1,但分配需要 2 位或 3 位的值。 重要的是要注意我从枚举中获取值。在此之后,我打印值。我希望得到等于 0 的整数的默认值。但我得到的是交替等于 0 或 1 的值。

你能解释一下原因吗?

下面是代码:

#include <stdio.h>

typedef enum {
    FIRST = 9,
    SECOND = 8,
    THIRD = 7,
    FOURTH = 6,
    FIFTH = 5,
    SIXTH = 4,
    SEVENTH = 3,
    EIGHTH = 2
} directionValues;

struct {
    unsigned int enough : 3;
    unsigned int not_enough: 1; //intentionally limited to 1 bit
} test_bit;

int main(void) {

    test_bit.enough = EIGHTH;
    printf("Enough bits for variable. Value is %d\n",test_bit.enough);

    test_bit.not_enough = THIRD;
    printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
    test_bit.not_enough = FOURTH;
    printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
    test_bit.not_enough = FIFTH;
    printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
    test_bit.not_enough = SIXTH;
    printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
    test_bit.not_enough = SEVENTH;
    printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
    test_bit.not_enough = EIGHTH;
    printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);

    return 0;
}

输出是:

足够的变量位。值为 2

变量位数不足。值为 1

变量位数不足。值为 0

变量位数不足。值为 1

变量位数不足。值为 0

变量位数不足。值为 1

变量位数不足。值为 0

【问题讨论】:

  • “重要的是要注意我从枚举中获取值” - 不,不是!而且您使用 enum-constants,而不是“枚举”类型。当您认为 1 不是 UB 时:您会接受哪种行为作为 UB?

标签: c testing struct enums bit-fields


【解决方案1】:

那是因为只有最后一位设置为您的变量,因为它只允许 1 位。

你实际上是这样做的:

test_bit.not_enough = 7; //(0111) Bit 0 is 1
printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
test_bit.not_enough = 6; //(0110) Bit 0 is 0
printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
test_bit.not_enough = 5; //(0101) Bit 0 is 1
printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
test_bit.not_enough = 4; //(0100) Bit 0 is 0
printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
test_bit.not_enough = 3; //(0011) Bit 0 is 1
printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);
test_bit.not_enough = 2; //(0010) Bit 0 is 0
printf("Not enough bits for variable. Value is %d\n",test_bit.not_enough);

由于您只有 1 位可用内存,因此只有第一位 (LSB) 设置为您的变量。

【讨论】:

    【解决方案2】:

    无论如何,什么是未定义的行为 - 您无法通过观察某些东西 不是 C 中的未定义行为来知道它可能是交替的 1 和 0 是未定义行为的一个示例。

    但是,C 标准规定在这种情况下没有未定义的行为。这些枚举的值通过取模 2 的值转换为 1 位宽的无符号整数。引用 C11 6.3.1.3

    1当一个整数类型的值被转换为_Bool以外的其他整数类型时,如果该值可以用新的类型表示,则不变。

    2 否则,如果新类型是无符号的,则通过在新类型中可以表示的最大值的基础上反复加或减一,直到该值是在新类型的范围内。 60)

    3 否则,新类型是有符号的,值不能在其中表示;结果要么是实现定义的,要么引发实现定义的信号。

    脚注 60 说明:

    这些规则描述的是数学值的算术运算,而不是给定类型表达式的值。

    任何整数值都可以转换为 1 位的 unsigned int 位域,而没有未定义的行为 - 甚至不是实现定义的。存储的值将是

    • 0,如果原始值是偶数
    • 1,如果原始值为奇数

    (偶数是0 + 2*k,奇数是1 + 2*k - 这里2k 匹配*重复加或减一个,比新类型可以表示的最大值多一倍” - 即2 被加或减 |k| 次。

    或者,如果原始数字是无符号的,则存储的值是最低有效位;如果原始数字是有符号的并且实现使用 2 的补码表示,则存储的值再次是最低有效位。

    【讨论】:

    • @Anhtti 看来tilz0R的回答是正确的。例如,如果我将宽度更改为 2 位并且所有值都等于 7,我总是得到值 = 3(二进制中的 7 = 111,使用 2 位,然后二进制中的 3 = 11)。你能用你上面的陈述解释一下吗?为什么在这种情况下重复加减不工作?
    猜你喜欢
    • 1970-01-01
    • 2021-01-23
    • 2017-06-16
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多