当前位置:  开发笔记 > 编程语言 > 正文

C++ struct alignment问题

如何解决《C++structalignment问题》经验,为你挑选了2个好方法。

我有一个预定义的结构(实际上是几个),其中变量跨越32位字边界.在Linux(以及使用GCC的Windows)中,我能够使用'attribute((packed))'将我的结构打包到正确的大小.但是我无法使用VC++和#pragma pack以相同的方式工作.

使用GCC,返回正确的6字节大小:

struct
{
    unsigned int   a                : 3;
    unsigned int   b                : 1;
    unsigned int   c                : 15;
    unsigned int   troubleMaker     : 16;
    unsigned short padding          : 13;
} __attribute__((packed)) s;

使用VC++,这将返回不正确的8字节大小

#pragma pack(push)
#pragma pack(1)

struct
{
    unsigned int   a                : 3;
    unsigned int   b                : 1;
    unsigned int   c                : 15;
    unsigned int   troubleMaker     : 16;
    unsigned short padding          : 13;
} s;

#pragma pack(pop)

我可以通过手动将"troubleMaker"分割成边界来实现工作,但我不愿意.有任何想法吗?



1> DigitalRoss..:

疯狂的想法:首先编写一个符合C99或C++ 03的程序


我建议不要使用特定于供应商的C语言扩展来匹配设备或网络位格式.即使您使用一系列每个供应商的语言扩展来排列字段,您仍然需要担心字节顺序,并且您仍然需要一个需要额外指令才能访问的结构布局.

您可以使用标准化的C API字符串和内存复制函数以及Posix hton和ntoh函数编写符合C99标准的程序,该程序可以在任何体系结构或主机上以最高速度和缓存效率运行.

一个好的做法是使用已发布标准的以下函数:

C99: memcpy(), Posix: htonl(), htons(), ntohl(), ntohs()

更新:这里有一些代码应该在任何地方都一样.如果Microsoft 仍然没有为C99实现它,或者只是对int size做出通常的假设,那么你可能需要从这个项目中获取.

#include 
#include 
#include 
#include 
#include 

struct packed_with_bit_fields {  // ONLY FOR COMPARISON
    unsigned int   a        : 3;
    unsigned int   b        : 1;
    unsigned int   c        : 15;
    unsigned int   troubleMaker : 16;
    unsigned short padding  : 13;
} __attribute__((packed));       // USED ONLY TO COMPARE IMPLEMENTATIONS

struct unpacked { // THIS IS THE EXAMPLE STRUCT
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t troubleMaker;
}; // NOTE NOT PACKED

struct unpacked su;
struct packed_with_bit_fields sp;
char *bits = "Lorem ipsum dolor";

int main(int ac, char **av) {
  uint32_t x;   // byte order issues ignored in both cases

  // This should work with any environment and compiler
  memcpy(&x, bits, 4);
  su.a = x & 7;
  su.b = x >> 3 & 1;
  su.c = x >> 4 & 0x7fff;
  memcpy(&x, bits + 2, 4);
  su.troubleMaker = x >> 3 & 0xffff;

  // This section works only with gcc
  memcpy(&sp, bits, 6);
  printf( sp.a == su.a
      &&  sp.b == su.b
      &&  sp.c == su.c
      &&  sp.troubleMaker == su.troubleMaker
      ? "conforming and gcc implementations match\n" : "huh?\n");
  return 0;
}


当然,系统工作通常是遗留代码,我有同情心.我只是写了标题的方式来吓唬任何新人,他们为下一个可怜的家伙编写符合规范的代码来进行维护.:-)

2> Paul Lalonde..:

位域的对齐和排序是众所周知的特定于实现的.这是很多安全声明一个正常的整型字段,并使用口罩和位内操纵"位域"(|&^)运营商.

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有