代码之家  ›  专栏  ›  技术社区  ›  Joseph Garvin

是否可以在使用不同编译器编译的应用程序之间共享共享内存中的C结构?

  •  2
  • Joseph Garvin  · 技术社区  · 15 年前

    我假设在同一体系结构的两个编译器中包含的类型的大小是一致的(因为我们讨论的是共享内存,所以它必须已经是同一个平台)。我意识到对于某些类型(例如GCC和MSVC 64位中的long和long long)并不总是这样,但是现在有uint16、uint32等类型,float和double由IEEE标准指定。

    5 回复  |  直到 15 年前
        1
  •  2
  •   JaredPar    15 年前

    只要您能保证完全相同的内存布局,包括偏移量,并且两个编译器之间的数据类型具有相同的大小,那么可以。因为在这一点上,结构与数据访问是相同的。

        2
  •  1
  •   wallyk    15 年前

    是的,当然。我做过很多次了。无论是将混合代码编译并链接在一起,还是在计算机之间传输结构格式的数据,问题和解决方案都是相同的。

    在过去糟糕的日子里,这经常发生在集成MS C和几乎任何其他东西时:Borland Turbo C.DEC VAX C,Greenhills C。

    short 在一个32位编译器上,一边与 int 在另一端的16位编译器上。由于用于声明结构的通用源代码通常是一件好事,因此许多to-the-point声明非常有用:

    typedef  signed long     s32;
    typedef  signed short    s16;
    typedef  signed char     s8;
    typedef  unsigned long   u32;
    typedef  unsigned short  u16;
    typedef  unsigned char   u8;
    ...
    

    微软C是最烦人的。它的默认设置是将成员填充到16位对齐,可能更多的是使用64位代码。x86上的其他编译器不填充成员。

    struct {
        int   count;
        char  type;
        char  code;
        char  data [100];
    } variable;
    

    它看起来像是 code 应该是后面的下一个字节 type ,但中间可能插入了一个填充字节。修复通常是

    #ifdef _MSC_VER    // if it's any Microsoft compiler
     #pragma pack(1)   // byte align structure members--that is, no padding
    #endif
    

    还有一个编译器命令行选项来执行同样的操作。

        3
  •  0
  •   wrapperm    15 年前

        4
  •  0
  •   bta    15 年前

    确实有可能,您只需确保所有涉及的编译器都从同一代码生成相同的数据结构。一种测试方法是编写一个示例程序,该程序创建一个结构并将其写入二进制文件。在十六进制编辑器中打开结果文件并验证它们是否相同。或者,可以将结构转换为 uint8_t 并将各个字节转储到屏幕上。

    确保数据大小相同的一种方法是使用如下数据类型 int16_t (来自stdint.h)而不是普通的 int 这可能会改变编译器之间的大小(虽然这在同一平台上运行的两个编译器上很少见)。

    这不像听起来那么难。有许多预编译的库可以与多个编译器一起使用。关键是要构建一个测试程序,让您验证两个编译器对结构的处理是否相同。

        5
  •  0
  •   Potatoswatter    14 年前

    大多数编译器都提供了扩展,允许您修复成员的对齐方式

    你是否把自己限制在那些编译器和相互兼容的 #pragma align 风格?如果是的话,安全性取决于它们的规格。

    为了便于移植,您最好放弃 #杂注对齐 并且依赖于您的ABI,它可以为您平台的所有编译器的遵从性提供一个“合理”的标准。

    推荐文章