【发布时间】:2018-02-01 21:39:48
【问题描述】:
有时需要将数据结构转换为指针,以便数据可以发送,例如,通过接口发送,或写出到其他流。在这些情况下,我通常会这样做:
typedef struct {
int field1;
char field2;
} testStruct;
int main()
{
char *buf;
testStruct test;
buf = (char *)&test;
// write(buf, sizeof(test)) or whatever you need to do
return 0;
}
然而,最近在一些微处理器代码中,我看到了类似的东西:
typedef struct {
int field1;
char field2;
} testStruct;
int main()
{
char buf[5];
testStruct test;
*(testStruct *)buf = test;
// write(buf, sizeof(test)) or whatever you need to do
return 0;
}
对我来说,前者感觉更安全一些。您只有一个指针,然后将结构的地址分配给指针。
在后一种情况下,如果您不小心为数组buf 分配了错误的大小,您最终会出现未定义的行为或段错误。
启用优化后,我收到来自 gcc 的 -Wstrict-aliasing 警告。但是,同样,这段代码在微处理器上运行,所以我可能会在那里遗漏一些东西吗?
结构中没有指针或任何东西,它非常简单。
【问题讨论】:
-
你之前的两个问题是这个:stackoverflow.com/questions/48571295/…
-
这个问题与
memcpy或一般的深拷贝无关。更多的是关于将数据结构转换为缓冲区的正确方法。 -
(testStruct *)buf可能会为testStruct生成未对齐的地址,从而导致总线故障。不使用。union更好。 -
write和朋友使用void *作为缓冲区参数,因此不需要强制转换。write(fd, &test, sizeof(test))完全可以,只要您考虑到平台差异。*(testStruct *)buf = test;不会通过代码审查。 -
除了运行未对齐的数据访问的相当严重的风险之外,
*(testStruct *)buf = test是一个坏主意(我会说实际上是一个非常愚蠢的主意),因为它不必要地复制数据。如果您有test,但您只是想暂时将其视为一个 blob o' 字节,那么相当于buf = (unsigned char *)&test就是您想要的。 (或者,如果您真的想复制数据,请致电memcpy。但强制转换和假装结构分配只是一个坏主意,它是 C 早期粗糙、无赖的遗留物。)