我有两个具有相同数据成员的结构。 (一个是 big_endian 结构,另一个是 little_endian ),现在我必须与它们进行相互转换。但是当我编写代码时,我发现有很多重复的代码,几乎没有变化。如果没有重复的代码,如何更改这些代码以使其更美观? (重复的代码表示这些代码可能相似,例如mode == 1
和mode == 2
,它们的分配位置不同。它看起来不雅,但可以使用。)
这是我的代码:
#pragma scalar_storage_order big-endian
typedef struct {
int a1;
short a2;
char a3;
int a4;
} test_B;
#pragma scalar_storage_order default
typedef struct {
int a1;
short a2;
char a3;
int a4;
} test_L;
void interconvert(test_L *little, test_B *big, int mode) {
// if mode == 1 , convert little to big
// if mode == 2 , convert big to little
// it may be difficult and redundant when the struct has lots of data member!
if(mode == 1) {
big->a1 = little->a1;
big->a2 = little->a2;
big->a3 = little->a3;
big->a4 = little->a4;
}
else if(mode == 2) {
little->a1 = big->a1;
little->a2 = big->a2;
little->a3 = big->a3;
little->a4 = big->a4;
}
else return;
}
注意:由于#pragma scalar_storage_order
答案 0 :(得分:-1)
发布了一个答案,建议使用memcpy解决此问题,但该答案已删除。实际上,如果使用正确,答案是正确的,我想解释原因。
OP指出的#pragma是中央的,
注意:由于#pragma scalar_storage_order
,以上代码必须在gcc-7或更高版本上运行
OP中的结构:
#pragma scalar_storage_order big-endian
typedef struct {
int a1;
short a2;
char a3;
int a4;
} test_B;
表示指令“ test_B.a2 = 256”在属于a2成员的两个连续字节中分别写入1和0。这是big-endian。类似的指令“ test_L.a2 = 256”将替代字节0和1(小尾数)。
以下memcpy:
memcpy(&test_L, &test_B, sizeof test_L)
将使test_L.a2的字节等于1和0,因为这是test_B.a2的RAM内容。但是现在,在小字节序模式下读取test_L.a2,这两个字节表示1。我们写入256,然后回读1。这正是所需的转换。
要正确使用此机制,只需在一个结构中编写memcpy()并在另一个结构中逐个读取另一个结构就足够了。大字节序变成小字节序,反之亦然。当然,如果要详细说明数据并对其进行计算,则重要的是要知道数据的字节序;如果它与默认模式匹配,则在计算之前不必执行任何转换,但必须稍后应用转换。相反,如果传入的数据与处理器的“默认字节序”不匹配,则必须先对其进行转换。
编辑 在下面的OP评论之后,我进行了更多调查。我看了一下这个https://gcc.gnu.org/onlinedocs/gcc/Structure-Layout-Pragmas.html
嗯,有三种#pragma可以选择字节布局: big-endian , little-endian 和 default 。前两个等于最后一个:如果目标计算机为little-endian,则默认为little-endian;否则为false。如果是big-endian,则默认为big-endian。这不只是逻辑上的。
因此,在big-endian和default之间进行memcpy()不会对big-endian机器产生任何影响。这也是合乎逻辑的。好的,更好的是,我要强调的是memcpy()本身绝对不会做任何事情:它只会将数据从以某种方式处理的ram区域移到以另一种方式处理的另一个区域。仅当完成普通成员访问后,才会对两个不同的区域进行不同的处理:这里是播放 #pragma scalar_storage_order 的过程。正如我之前写的,了解哪些字节序的数据进入程序很重要。例如,如果它们来自TCP网络,则我们知道这是big-endian。更一般而言,如果它是从“程序”外部获取并遵守协议,则我们应该知道字节序的含义。
要从字节序转换为另一字节序,应使用 little 和 big , NOT 默认值,因为 default < / em>肯定等于前两个之一。
受评论的刺激,以及使用在线编译器的Jamesdlin的启发,我也尝试这样做。在此网址http://tpcg.io/lLe5EW 有一个示例说明了将一个成员分配给一个结构,将memcpy分配给另一个结构,并读完后,进行了字节序转换。就是这样。