问题
I have come across a strange behavior on signed bit-fields:
#include <stdio.h>
struct S {
long long a31 : 31;
long long a32 : 32;
long long a33 : 33;
long long : 0;
unsigned long long b31 : 31;
unsigned long long b32 : 32;
unsigned long long b33 : 33;
};
long long f31(struct S *p) { return p->a31 + p->b31; }
long long f32(struct S *p) { return p->a32 + p->b32; }
long long f33(struct S *p) { return p->a33 + p->b33; }
int main() {
struct S s = { -2, -2, -2, 1, 1, 1 };
long long a32 = -2;
unsigned long long b32 = 1;
printf("f31(&s) => %lld\n", f31(&s));
printf("f32(&s) => %lld\n", f32(&s));
printf("f33(&s) => %lld\n", f33(&s));
printf("s.a31 + s.b31 => %lld\n", s.a31 + s.b31);
printf("s.a32 + s.b32 => %lld\n", s.a32 + s.b32);
printf("s.a33 + s.b33 => %lld\n", s.a33 + s.b33);
printf(" a32 + b32 => %lld\n", a32 + b32);
return 0;
}
Using Clang on OS/X, I get this output:
f31(&s) => -1 f32(&s) => 4294967295 f33(&s) => -1 s.a31 + s.b31 => 4294967295 s.a32 + s.b32 => 4294967295 s.a33 + s.b33 => -1 a32 + b32 => -1
Using GCC on Linux, I get this:
f31(&s) => -1 f32(&s) => 4294967295 f33(&s) => 8589934591 s.a31 + s.b31 => 4294967295 s.a32 + s.b32 => 4294967295 s.a33 + s.b33 => 8589934591 a32 + b32 => -1
The above output shows 3 types of inconsistencies:
- different behavior for different compilers;
- different behavior for different bit-field widths;
- different behavior for inline expressions and equivalent expressions wrapped in a function.
The C Standard has this language:
6.7.2 Type specifiers
...
Each of the comma-separated multisets designates the same type, except that for bit-fields, it is implementation-defined whether the specifier
int
designates the same type assigned int
or the same type asunsigned int
.
Bit-fields are notoriously broken in many older compilers...
Is the behavior of Clang and GCC conformant or are these inconsistencies the result of one or more bugs?
来源:https://stackoverflow.com/questions/58846584/multiple-inconsistent-behavior-of-signed-bit-fields