使用联合强制 C 位域对齐
我想知道是否可以在 C 中强制对齐位域。使用下面代码中的变量我知道写入 _align_bytes 然后从 bits 读取是未定义的(反之亦然)因为它取决于实现。下面的代码是否是“说服”位连续存储在无符号短整型大小的内容中的有效方法?我相信(减去任何字节序问题)此代码是正确的...但位域和联合是我最不熟悉的两个 C 主题。
我正在做一个低级微控制器项目,并且想要一种无需大量位掩码即可读取配置位的简单方法。感谢您的任何提示和建议。
山姆·
P.S.请忽略我对字节顺序所做的任何假设,因为我正在从事的这个项目的级别非常低,并且不打算移植到其他设备/平台。
#include <stdio.h>
#include <assert.h>
typedef union packet {
struct {
unsigned int bit0 : 1;
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8 : 1;
unsigned int bit9 : 1;
unsigned int bit10 : 1;
unsigned int bit11 : 1;
unsigned int bit12 : 1;
unsigned int bit13 : 1;
unsigned int bit14 : 1;
unsigned int bit15 : 1;
} bits;
unsigned short _align_bytes;
} packet_t;
int main(int argc, char *argv[]) {
assert(sizeof(unsigned short) == 2);
unsigned short data = 0xA05F;
packet_t *p = (packet_t *)&data;
printf("%u", p->bits.bit15);
printf("%u", p->bits.bit14);
printf("%u", p->bits.bit13);
printf("%u", p->bits.bit12);
printf("%u", p->bits.bit11);
printf("%u", p->bits.bit10);
printf("%u", p->bits.bit9);
printf("%u", p->bits.bit8);
printf("%u", p->bits.bit7);
printf("%u", p->bits.bit6);
printf("%u", p->bits.bit5);
printf("%u", p->bits.bit4);
printf("%u", p->bits.bit3);
printf("%u", p->bits.bit2);
printf("%u", p->bits.bit1);
printf("%u", p->bits.bit0);
return 0;
}
I was wondering if it is possible to force the alignment of bitfield in C. Using the variables in the code below I know that writing to _align_bytes then reading from bits is undefined (and vice-versa) because it is implementation depended. Is the code below a valid method to "persuade" bits to be stored contiguously in something that is the size of unsigned short? I believe that (minus any endian issues) this code is correct... but bitfields and unions are the two C topics I am least familiar with.
I am doing a low level micro-controller project and would like an easy method of reading configuration bits without a ton of bit masking. Thanks for any tips and suggestions.
Sam
P.S. Please disregard any assumptions I make about endianness as this project I am working on is very low level and not intended to be ported to other devices/platforms.
#include <stdio.h>
#include <assert.h>
typedef union packet {
struct {
unsigned int bit0 : 1;
unsigned int bit1 : 1;
unsigned int bit2 : 1;
unsigned int bit3 : 1;
unsigned int bit4 : 1;
unsigned int bit5 : 1;
unsigned int bit6 : 1;
unsigned int bit7 : 1;
unsigned int bit8 : 1;
unsigned int bit9 : 1;
unsigned int bit10 : 1;
unsigned int bit11 : 1;
unsigned int bit12 : 1;
unsigned int bit13 : 1;
unsigned int bit14 : 1;
unsigned int bit15 : 1;
} bits;
unsigned short _align_bytes;
} packet_t;
int main(int argc, char *argv[]) {
assert(sizeof(unsigned short) == 2);
unsigned short data = 0xA05F;
packet_t *p = (packet_t *)&data;
printf("%u", p->bits.bit15);
printf("%u", p->bits.bit14);
printf("%u", p->bits.bit13);
printf("%u", p->bits.bit12);
printf("%u", p->bits.bit11);
printf("%u", p->bits.bit10);
printf("%u", p->bits.bit9);
printf("%u", p->bits.bit8);
printf("%u", p->bits.bit7);
printf("%u", p->bits.bit6);
printf("%u", p->bits.bit5);
printf("%u", p->bits.bit4);
printf("%u", p->bits.bit3);
printf("%u", p->bits.bit2);
printf("%u", p->bits.bit1);
printf("%u", p->bits.bit0);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一种常见的模式,据我所知,答案是肯定的:位字段将是连续的,并与 _align_bytes 字段占用相同的内存。这就是工会的全部意义,对吗?以不同的方式看待同一个记忆。
我不确定“写入 _align_bytes 然后从位读取未定义”是什么意思。我看到的唯一问题是字节顺序:bit0 可能是 _align_bytes 的 lsb 或 msb。如果您不希望它是便携式的,那么您只需要进行快速测试即可确定它是什么,然后就可以设置了。
This is a common pattern and as far as I know, the answer is yes: the bit fields will be contiguous and occupy the same memory as the _align_bytes field. That's the whole point of a union, right? Different ways of looking at the same memory.
I'm not sure what you mean by "writing to _align_bytes then reading from bits is undefined". The only issue I see is the endianess: bit0 may be the lsb or the msb of _align_bytes. If you don't want it to be portable, then you just need to do a quick test to figure out which it is, and you should be set.
我不确定,但这不会违反 严格的别名规则 因为两个不同类型的指针指向同一个内存位置?在 C89 和 C99 中,不保证您能正确返回任何内容。
您可能想对此进行测试,如果需要,请使用
-fno-strict-aliasing
或类似的编译器,以便它禁用可能导致问题的严格别名。I am not sure, but wouldn't this violate strict aliasing rules because two pointers of different types are pointing to the same memory location? In C89 and C99 you are not guaranteed to get anything back correctly.
You may want to test this, and if required use
-fno-strict-aliasing
or something similar for your compiler so that it disables strict aliasing which could cause issues.