结构中引用的间接指针的意外地址,而不是使用普通变量的相同声明?
我有一个包含字节数组和对数组中各个点的几个类型转换引用的结构。字节 4:7 可以解释为 float、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.**
}
我希望看到相同的指针地址、类型转换指针和间接指针的引用地址。我确实看到,如果我创建一个数组和指针/引用作为独立变量,但不是在结构中创建相同的声明。我缺乏什么神秘的知识来解释这种行为(或者我忽略了什么愚蠢的事情?)
我解决这个问题的想法是a)忽略它并根据需要对指针进行类型转换,或者b)创建一些setter / getter函数访问串行“数据包”的参数部分。
I have a struct containing a byte array and several typecast references to various points in the array. Bytes 4:7 may be interpreted as a float, int32_t, or uint32_t as determined by other fields in the packet being received over a serial connection. To make access simple (e.g. message.argument.F
for a float interpretation), I made multiple references to indirected typecast pointers. But when I ran the program, I got a segfault trying to write to the references in the struct. As near as I can tell, the problem has to do with the container, as illustrated by this example snippet (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.**
}
I expect to see the same address for the pointer, a typecast pointer, and the address of the reference for the indirected pointer. I do see that if I create an array and the pointer/reference as standalone variables, but not for the same declarations in a struct. What arcane knowledge do I lack to explain this behavior (or what silly thing have I overlooked?)
My thoughts for fixing this are to a) ignore it and just typecast the pointer as necessary instead, or b) make some setter/getter functions to access the argument portion of the serial "packet".
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这两个替代代码块之间有两个主要的、根本的区别。
在这里,它首先构造并初始化
argp
,然后构造和初始化argf
。但在这里,情况并非如此。
首先初始化
argf
,然后初始化argp
。这样做的后果应该是很明显的。注意:我在这里忽略了所有违反别名规则的行为,这可能是进一步未定义行为的根源。
There are two major, fundamental differences between the two alternative chunks of code.
Here, this constructs and initializes
argp
first, thenargf
.And here, it does not.
This initializes
argf
first, thenargp
. The consequences of this should be quite apparent.Note: I'm ignoring all the aliasing rule violations here, that are likely to be a source of further undefined behavior.