C++ 您可以在同一个联合中使用固定大小的类型和指针吗?

C++ 您可以在同一个联合中使用固定大小的类型和指针吗?,c++,unions,C++,Unions,我正在研究为数据包定义结构的可能性。我想在数据包中设置头变量,然后设置指向数据包数据部分的指针。我的最终目标是能够将此数据包发送到只需要一个uint8_t*的低级库。我创建了这个快速程序来测试可行性,但它似乎不起作用 #include <iostream> #include <cstdint> #include <stdlib.h> typedef union { struct { uint8_t header; ui

我正在研究为数据包定义结构的可能性。我想在数据包中设置头变量,然后设置指向数据包数据部分的指针。我的最终目标是能够将此数据包发送到只需要一个uint8_t*的低级库。我创建了这个快速程序来测试可行性,但它似乎不起作用

#include <iostream>
#include <cstdint>
#include <stdlib.h>

typedef union {
    struct {
        uint8_t header;
        uint8_t* data;
    };
    uint8_t* packet;
} sometype;

int main() {
    sometype s;
    s.header = 3;
    s.data = (uint8_t *) malloc(sizeof(uint8_t) * 2);
    s.data[0] = 1;
    s.data[1] = 2;

    for (unsigned int i = 0; i < 3; i++) {
        std::cout << s.packet[i] << std::endl;
    }

    std::cout << std::endl;

    std::cout << s.header << std::endl;
    std::cout << s.data[0] << std::endl;
    std::cout << s.data[1] << std::endl;
}
这让我意识到我的代码中存在某种类型的错误(我以前从未使用过union)。然而,当我调试程序时,我可以看到联合体中的数据。查看数据包,我可以看到此方法似乎不起作用。数据包中的数据不是3、1、2。而是300221020

(gdb) print s
$1 = {{header = 3 '\003', data = 0x613c20 "\001\002"}, packet = 0x400903 <main()+125> "\300\211ƿ`\020`"}
(gdb)打印
$1={{header=3'\003',data=0x613c20“\001\002”},packet=0x400903“\300\211ƿ`\020`}

我尝试的这个方法有效吗?从谷歌搜索中我看到有人说你可以使用任何你想要的数据类型。我是否必须使用pragma来打包结构才能使其工作,或者这种方法不可行?

是的,您必须使用pragma pack(1)来获得大多数工程师期望的行为。是的,这就是大多数通信低级软件的工作原理

否则,出于性能和兼容性原因,编译器倾向于将每个元素与其数据大小对齐


编译器之间存在着与
#pragma pack()
的巨大交叉兼容性。请参阅。

是的,您必须使用
#pragma pack(1)
来获得大多数工程师期望的行为。是的,这就是大多数通信低级软件的工作原理

否则,出于性能和兼容性原因,编译器倾向于将每个元素与其数据大小对齐


编译器之间存在着与
#pragma pack()
的巨大交叉兼容性。请参阅。

异常输出是因为您尝试使用
异常输出是因为您尝试使用
我添加了#pragma包(1),并且在尝试访问s.packet时出现了分段错误。如果我也尝试将s.packet传递给函数,这会导致分段错误吗?测试结果表明,这种方法似乎不可行。有什么建议可以实现我想要的行为吗?@rangeme:你在哪个CPU上执行这个程序?微处理器。我想我创建了一个缓冲区,并手动将数据放在正确的位置,然后将其与字节数一起传递给低级库。我想用一种更漂亮的方式,但它可以。我添加了#pragma包(1),当我尝试访问s.packet时,我遇到了一个分段错误。如果我也尝试将s.packet传递给函数,这会导致分段错误吗?测试结果表明,这种方法似乎不可行。有什么建议可以实现我想要的行为吗?@rangeme:你在哪个CPU上执行这个程序?微处理器。我想我创建了一个缓冲区,并手动将数据放在正确的位置,然后将其与字节数一起传递给低级库。想要一个更漂亮的方式,但它会做到。正如下面的答案所述,你真的不能这样做,因为工会成员占据相同的空间,这就是工会的意义所在。我认为这可能有助于你形象化这是如何运作的:正如下面的答案所述,你真的不能这么做,因为工会成员占据相同的空间,这就是工会的意义所在。我认为这可能有助于你形象地了解它是如何工作的:这就是使这种方法不可行的缺陷。我无法写入报头和数据变量,然后读取数据包变量。这是使此方法不可行的缺陷。我无法写入报头和数据变量,然后读取数据包变量。
(gdb) print s
$1 = {{header = 3 '\003', data = 0x613c20 "\001\002"}, packet = 0x400903 <main()+125> "\300\211ƿ`\020`"}