Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用并集强制C位字段对齐_C_Struct_Bit Fields_Memory Alignment_Unions - Fatal编程技术网

使用并集强制C位字段对齐

使用并集强制C位字段对齐,c,struct,bit-fields,memory-alignment,unions,C,Struct,Bit Fields,Memory Alignment,Unions,我想知道是否有可能强制C中的位字段对齐。使用下面代码中的变量,我知道写入\u align\u字节,然后从位读取是未定义的(反之亦然),因为这取决于实现。下面的代码是否是“说服”位连续存储在大小为unsigned short的内容中的有效方法?我相信(减去任何endian问题)这段代码是正确的。。。但是位域和联合是我最不熟悉的两个C主题 我正在做一个低水平的微控制器项目,并希望有一个简单的方法读取配置位没有一吨位掩蔽。谢谢你的提示和建议 萨姆 另外,请忽略我对endianness所做的任何假设,因

我想知道是否有可能强制C中的位字段对齐。使用下面代码中的变量,我知道写入\u align\u字节,然后从读取是未定义的(反之亦然),因为这取决于实现。下面的代码是否是“说服”连续存储在大小为unsigned short的内容中的有效方法?我相信(减去任何endian问题)这段代码是正确的。。。但是位域和联合是我最不熟悉的两个C主题

我正在做一个低水平的微控制器项目,并希望有一个简单的方法读取配置位没有一吨位掩蔽。谢谢你的提示和建议

萨姆

另外,请忽略我对endianness所做的任何假设,因为我正在从事的这个项目级别非常低,不打算移植到其他设备/平台

#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;
}
#包括
#包括
typedef联合包{
结构{
无符号整数位0:1;
无符号整数位1:1;
无符号整数位2:1;
无符号整数位3:1;
无符号整数位4:1;
无符号整数位5:1;
无符号整数位6:1;
无符号整数位7:1;
无符号整数位8:1;
无符号整数位9:1;
无符号整数位10:1;
无符号整数位11:1;
无符号整数位12:1;
无符号整数位13:1;
无符号整数位14:1;
无符号整数位15:1;
}比特;
无符号短对齐字节;
}数据包;
int main(int argc,char*argv[]){
断言(sizeof(无符号短)==2);
无符号短数据=0xA05F;
数据包p=(数据包t*)和数据;
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);
返回0;
}

这是一种常见模式,据我所知,答案是肯定的:位字段将是连续的,并占用与_align_bytes字段相同的内存。这就是工会的全部意义,对吗?看同一个记忆的不同方式


我不确定你所说的“写入对齐字节,然后读取位是未定义的”是什么意思。我看到的唯一问题是endianess:位0可能是_align_字节的lsb或msb。如果你不希望它是可移植的,那么你只需要做一个快速测试来确定它是哪一个,然后你就应该设置它。

我不确定,但这是否会违反,因为两个不同类型的指针指向同一个内存位置?在C89和C99中,不保证您能正确返回任何内容


您可能需要对此进行测试,如果需要,请为您的编译器使用
-fno strict aliasing
或类似的工具,以便它禁用可能导致问题的严格别名。

根据这一点,是的:您可能应该为
\u align\u位
使用相同的类型。如果您的int是不同的大小(例如sizeof(int)==4和sizeof(short)==2),并且位字段是按您不期望的顺序排列的,则
可能不会重叠
\u align\u位
。Endian属性和位字段顺序是不同的。“依赖于实现”不是“未定义”。而且,由于您使用的是微控制器编译器,这种黑客行为很常见,因此我认为您非常安全。因为,是的,这是强制位字段对齐/填充的正常方式。