【发布时间】:2021-02-03 06:43:47
【问题描述】:
我很难理解 C 中位字段的可移植性。假设我有一个共享库,仅由两个文件组成,libfoobar.h(公共标头)和libfoobar.c,内容如下:
libfoobar.h:
typedef struct some_bitfield_T {
unsigned char foo:3;
unsigned char bar:2;
unsigned char tree:2;
unsigned char window:1;
} some_bitfield;
extern unsigned int some_function (some_bitfield input);
libfoobar.c:
#include "libfoobar.h"
unsigned int some_function (some_bitfield input) {
return input.foo * 3 + input.bar + input.tree + 1 - input.window;
}
编译并安装库后,我使用名为test 的程序对其进行测试。
test.c:
#include <stdio.h>
#include <libfoobar.h>
int main () {
some_bitfield my_attempt = {
.foo = 6,
.bar = 3,
.tree = 1,
.window = 1
};
unsigned int some_number = some_function(my_attempt);
printf("Here is the result: %u\n", some_number);
return 0;
}
上面的test 程序是否有可能产生与以下输出不同的任何东西?
Here is the result: 22
如果是,什么时候?如果库是由我以外的其他人编译的怎么办?如果我为库和test 程序使用不同的编译器会怎样?
【问题讨论】:
-
位域通常不可移植。允许编译器重新排序成员,并且没有指定结构中可能的填充。
-
但这不适用于普通结构吗?
-
填充是的,所以共享库中使用的结构需要非常仔细地设计,成员之间没有任何填充。但对于普通结构,成员不能重新排列,这与位域不同。
-
但是为什么编译器要对一个字节内的成员重新排序呢?
-
Tom,如果编译器确实可以按照他们所说的那样重新排序成员,那么它可能不会在所有地方都显示 22。
标签: c portability bit-fields cc