是否可以在使用不同编译器编译的应用程序之间共享共享内存中的C结构? 我意识到C和C++标准一般给编译器编写者带来很大的自由度。但特别是,它保证了像C结构成员这样的POD类型在内存中的排列顺序必须与它们在结构定义中列出的顺序相同,并且大多数编译器提供了扩展,允许您修复成员的对齐方式。因此,如果您有一个定义了结构并手动指定其成员对齐方式的头,然后使用该头使用不同的编译器编译了两个应用程序,那么难道一个应用程序不能将结构实例写入共享内存,而另一个应用程序不能读取它而不会出错吗
我假设在同一体系结构的两个编译器中包含的类型的大小是一致的(因为我们讨论的是共享内存,所以它必须是同一个平台)。我意识到,对于某些类型(例如GCC和MSVC 64位中的long与long),这并不总是正确的,但现在有uint16_t、uint32_t等。IEEE标准规定了类型和float和double。只要您能保证完全相同的内存布局,包括偏移,两个编译器之间的数据类型大小相同,那么是的,这很好。因为在这一点上,结构在数据访问方面是相同的 如果需要编译器1编译的库1中的struct用于编译器2编译的库2中,那么除了数据类型大小之外,内存的布局方式也很重要。确实有可能,您只需确保所有涉及的编译器从相同的代码生成相同的数据结构。测试这一点的一种方法是编写一个示例程序,创建一个结构并将其写入二进制文件。在十六进制编辑器中打开生成的文件,并验证它们是否相同。或者,您可以将结构强制转换为是否可以在使用不同编译器编译的应用程序之间共享共享内存中的C结构? 我意识到C和C++标准一般给编译器编写者带来很大的自由度。但特别是,它保证了像C结构成员这样的POD类型在内存中的排列顺序必须与它们在结构定义中列出的顺序相同,并且大多数编译器提供了扩展,允许您修复成员的对齐方式。因此,如果您有一个定义了结构并手动指定其成员对齐方式的头,然后使用该头使用不同的编译器编译了两个应用程序,那么难道一个应用程序不能将结构实例写入共享内存,而另一个应用程序不能读取它而不会出错吗,c++,c,shared-memory,binary-compatibility,C++,C,Shared Memory,Binary Compatibility,我假设在同一体系结构的两个编译器中包含的类型的大小是一致的(因为我们讨论的是共享内存,所以它必须是同一个平台)。我意识到,对于某些类型(例如GCC和MSVC 64位中的long与long),这并不总是正确的,但现在有uint16_t、uint32_t等。IEEE标准规定了类型和float和double。只要您能保证完全相同的内存布局,包括偏移,两个编译器之间的数据类型大小相同,那么是的,这很好。因为在这一点上,结构在数据访问方面是相同的 如果需要编译器1编译的库1中的struct用于编译器2编译
uint8\t
数组,并将单个字节转储到屏幕上
确保数据大小相同的一种方法是使用类似于int16_t
(来自stdint.h)的数据类型,而不是可能在编译器之间更改大小的普通旧式int
(尽管在同一平台上运行的两个编译器上很少使用)
这并不像听起来那么难。有许多预编译库可以与多个编译器一起使用。关键是要构建一个测试程序,让您验证两个编译器是否平等地对待结构。是的,当然。我已经做过很多次了。无论是编译和链接混合代码,还是在机器之间传输结构化数据,问题和解决方案都是相同的 在糟糕的过去,这种情况经常发生在集成MS C和其他几乎任何东西时:Borland Turbo C.DEC VAX C、Greenhills C 最简单的部分是获得各种数据类型所需的字节数。例如,32位编译器一端的
short
与16位编译器另一端的int
相同。由于用于声明结构的通用源代码通常是一件好事,因此一些直接的声明非常有用:
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
还有一个编译器命令行选项可以执行同样的操作。请参阅编译器手册 大多数编译器都提供扩展,允许您修复成员的对齐方式 您是否仅限于使用这些编译器和相互兼容的
#pragma align
样式?如果是这样,安全性由其规格决定
为了便于移植,您最好放弃#pragma align
并依赖您的ABI,它可能为您平台的所有编译器提供一个“合理”的合规标准
<> P>因为C和C++标准允许任何确定性结构布局方法,它们本质上是不相关的。< /P> @ Trent,这取决于,如果你能用可怕的语法或语言的拐角来保证这些保证,那么它肯定会起作用。然而,做出这样的保证是非常困难的IMHO@Trent:这与使用structs在网络上读/写数据时的“yes but”响应几乎相同。使用结构来表示序列化/封送的数据是应用程序的一个细节,如果您能保证结构是正确的,这可能会很方便。不同C实现之间的二进制数据可能被认为是“序列化的”:不管它是通过网络共享的还是在共享RAM中共享的,同样的问题也适用于类型和布局可能不匹配的情况。一个数组和一个流都可以看作是一个字符序列。至少在同一台主机上共享内存时,您不会有endian问题。难道以前的动态链接库不是每天都在这样做吗?它不必是共享内存,两个库之间或一个库和独立编译的应用程序之间的结构面临相同的问题。库可以用PIC编译,但这不会改变结构的布局。当库共享相同的ABI时。对于不同编译器而不是C++编译器编译的C库来说,这通常是正确的。