代码之家  ›  专栏  ›  技术社区  ›  Daniel B.

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

  •  0
  • Daniel B.  · 技术社区  · 3 年前

    我有一个结构,其中包含一个字节数组和对数组中不同点的几个类型转换引用。字节4:7可被解释为浮点、int32_t或uint32_t,由通过串行连接接收的数据包中的其他字段确定。使访问变得简单(例如。 message.argument.F 对于浮点解释),我多次引用间接类型转换指针。但当我运行程序时,我在试图写入结构中的引用时遇到了一个segfault。据我所知,问题与容器有关,如以下示例片段所示(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.**
    }
    

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

    我解决这个问题的想法是a)忽略它,根据需要键入指针,或者b)使用一些setter/getter函数来访问串行“数据包”的参数部分。

    1 回复  |  直到 3 年前
        1
  •  2
  •   Sam Varshavchik    3 年前

    这两种代码块之间有两个主要的、根本的区别。

        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 首先,然后 阿格普 .这样做的后果应该非常明显。

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