C++结构对齐问题

标签 c++ memory gcc visual-c++

我有一个预定义的结构(实际上是几个),其中变量跨越 32 位字边界。在 Linux(和使用 GCC 的 Windows)中,我可以使用“属性((打包))”将我的结构打包到正确的大小。但是,我无法使用 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' 跨边界拆分来让事情正常工作,但我不希望这样做。有什么想法吗?

最佳答案

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


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

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

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

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

更新:这里有一些代码应该在任何地方都可以正常工作。您可能需要获取 <stdint.h> from this project如果微软仍然没有为 C99 实现它,或者只是对 int 大小做出通常的假设。

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>

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;
}

关于C++结构对齐问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1455458/

相关文章:

c++ - 交替排序数组的最简单方法是什么(例如 :T, T,F,F,F,T,F,T,F,F,F 到 T,F,T,F,T,F,T,F,T,T ,T)?

c++ - 你怎么知道你是否可以将一个类型 static_cast 为一个不同的类型?

c++ - 具有 64 位基础整数的枚举

c - 如何使用 gcc 4.8.4 [-Wunused-parameter] 摆脱 C 中的未使用参数警告

c++ - 如果我知道每个索引处的字符,如何创建字符串(在C++中)

c++ - 如何初始化复杂对象的数组?

c++ - 指针和引用如何保存在内存中

linux - centos 中每个进程的磁盘 IO

Java (JNA API) - 计算基地址

c - 结构数组