C可变宽度位域

标签 c gcc struct

我在这里问的问题不多,所以如果我的“提问技巧”有点生疏,请原谅我。开始了:


我环顾四周,似乎找不到解决办法。

这个想法是程序打印出一个表,其中包含具有任意位大小的数字的每个可能值的十进制(有符号和无符号)、十六进制和二进制表示形式。它接受来自 argv 的位大小,示例输出应该是(关注二进制表示):

$ ./test 2
00
01
10
11
$ ./test 4
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

如果我使用预处理器宏,这会很好地工作,但这意味着每次我想更改位大小时都必须重新编译。如果不是因为一个小警告,Argv 将解决我所有的问题。那就是编译器不喜欢我正在尝试做的事情,即使它看起来完全合乎逻辑。

我想做的是:

int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;

但是编译器给我一个错误,非常严厉地告诉我我不能那样做(“bitfield not an integer constant”)。

好吧...所以我尝试使用 const int 代替:

const int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;

我得到了完全相同的错误。

请注意:GCC 我做的是:

struct { unsigned int a : 8; } test;

而且它没有任何问题。但我需要能够改变它。

我很困惑。

请注意,我不希望或不需要位域的宽度能够在程序中更改,这是我假设 GCC 试图阻止我做的事情。这实际上是一次操作。

另请注意,我并没有尝试对像 this question 这样的普通变量执行此操作(还有许多其他人喜欢它)。

This question也与我想要完成的事情无关。


另外,如果有帮助的话,这是一个无错误运行时显示的示例(位域宽度 = 4):

$ ./test 4
$ cat table.md
Table for a/an 4-bit integer: 

| Unsigned | Signed | Hex | Binary | Sign Bit |
|:--------:|:------:|:---:|:------:|:--------:|
|    0     |   0    |  0  |  0000  |    0     |
|    1     |   1    |  1  |  0001  |    0     |
|    2     |   2    |  2  |  0010  |    0     |
|    3     |   3    |  3  |  0011  |    0     |
|    4     |   4    |  4  |  0100  |    0     |
|    5     |   5    |  5  |  0101  |    0     |
|    6     |   6    |  6  |  0110  |    0     |
|    7     |   7    |  7  |  0111  |    0     |
|    8     |   -8   |  8  |  1000  |    1     |
|    9     |   -7   |  9  |  1001  |    1     |
|    10    |   -6   |  A  |  1010  |    1     |
|    11    |   -5   |  B  |  1011  |    1     |
|    12    |   -4   |  C  |  1100  |    1     |
|    13    |   -3   |  D  |  1101  |    1     |
|    14    |   -2   |  E  |  1110  |    1     |
|    15    |   -1   |  F  |  1111  |    1     |

最佳答案

您不能在运行时在 C 中定义位字段的大小。但是您不需要位字段来打印二进制值,只需编写一个函数来打印二进制格式的数字,例如一个在这里: Is there a printf converter to print in binary format?

然后写一个简单的循环来打印你的数字:

//get n
for (int i = 0; i < n; i++) {
    print_binary(i);
}

编辑: 要回答有关打印以二进制补码编码的负数的问题,这些负数在 C 中没有 native 类型(如 int8_t、int16_t、int32_t..),就像您发现在 2 的补码中编码为 N 位的有符号字一样,对于负数您可以使用相等的数字:

Xnegative = 2^N - Xpositive

//get n
for (uint32_t Xpos = 0; Xpos < (1<<n); Xpos++) {
    if (Xpos > 1<<(n-1))
        printf("%d\n", -(1 << n) + Xpos);
    else
        printf("%u\n", Xpos);
}

关于C可变宽度位域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23160614/

相关文章:

c++ - fstream 文件 I/O 问题 - 何时关闭文件流

c++ - 初学者有什么实际使用的好项目

c++ - g++和gcc有什么区别?

c - 如何通过引用将创建的指针数组传递到结构中?

C++ 访问 URL 的最快方法

c - 使用 pthread_create 和 pthread_detach 时出错

c - C中结构体的实际大小是多少

c++ - 具有虚拟析构函数的类的未使用 const 对象会导致段错误

c - 结构中的结构数组 (C)

c - 结构体c简单问题