结构中引用的间接指针的意外地址与普通变量的相同声明相反?

unexpected address for a referenced indirected pointer in a struct as opposed to same declaration with a plain variable?

我有一个结构,其中包含一个字节数组和对数组中各个点的多个类型转换引用。字节 4:7 可能被解释为浮点数、int32_t 或 uint32_t,由通过串行连接接收的数据包中的其他字段确定。为了使访问变得简单(例如 message.argument.F 用于浮点解释),我对间接类型转换指针进行了多次引用。但是当我 运行 程序时,我在尝试写入结构中的引用时遇到段错误。据我所知,问题与容器有关,如示例片段 (cpp shell: http://cpp.sh/3vmoy):

所示
#include <iostream>
#include <cstring>
using namespace std;

#define PACKET_SIZE 9
#define ARG_I 4

struct Message{
  uint8_t bytes[PACKET_SIZE];
  uint8_t* argbytes = static_cast<uint8_t*>(argp);
  float& argf = *static_cast<float*>(argp);
  void* argp = &bytes[ARG_I];
} message;



int main(){
    // USING STRUCT    
    cout << "Using message struct" << endl;
    cout << message.argp << endl;                           // the pointer at index stored in struct
    cout << static_cast<float*>(message.argp) << endl;      // casting the pointer to a float* - should be the same
    cout << &message.argf << endl;                          // the address of the float reference cast from argp, ** should be the same BUT IS NOT **
    
    // RAW VARS
    uint8_t bytes[PACKET_SIZE];
    void* argp = &bytes[ARG_I];
    float& argf = *static_cast<float*>(argp);

    cout << endl << "using raw vars" << endl;
    cout << argp << endl;                                   // a pointer to a byte in an array of bytes.
    cout << static_cast<float*>(argp) << endl;              // the same pointer cast as a float*
    cout << &argf << endl;                                  // the address of a float reference cast from argp, **should be the same AND IS.**
}

我希望看到相同的指针地址、类型转换指针和间接指针的引用地址。我 do 看到如果我创建一个数组和 pointer/reference 作为独立变量,但不是针对结构中的相同声明。我缺乏什么神秘的知识来解释这种行为(或者我忽略了什么愚蠢的事情?)

我解决这个问题的想法是 a) 忽略它并根据需要对指针进行类型转换,或者 b) 创建一些 setter/getter 函数来访问串行“数据包”的参数部分。

两个可供选择的代码块之间有两个主要的根本区别。

    void* argp = &bytes[ARG_I];
    float& argf = *static_cast<float*>(argp);

这里先构造初始化argp,再构造初始化argf.

  float& argf = *static_cast<float*>(argp);
  void* argp = &bytes[ARG_I];

而在这里,它没有。

这会先初始化 argf,然后 argp。这样做的后果应该是很明显的。

注意:我在这里忽略了所有违反别名规则的行为,它们很可能是进一步未定义行为的来源。