纪念结构变量
memcpy structure variables
这听起来很基本的问题,但是我在C 中有关注结构:
struct SMessage
{
unsigned int id;
unsigned int payloadSize;
unsigned char data[100];
unsigned char *data2;
};
可以说,我有两个Smessage类型的变量(MSG1,MSG2),我想将MSG1的个体成员纳入MSG2(请不要问为什么!)。我知道复制ID和有效负载相对直接:
memcpy(&msg2.id, &msg1.id, sizeof(unsigned int));
memcpy(&msg2.payLoadSize, &msg2.payLoadSize, sizeof(unsigned int));
,但是要复制数据[]我们应该这样做:
memcpy(&msg2.data, &msg1.data, 100*sizeof(unsigned char));
或
memcpy(msg2.data, msg2.data, 100*sizeof(unsigned int))
也可以工作,因为数据是一个数组对象?
我们将如何复制struct成员data2,该构件data2被声明为指针?
任何一个版本都可以使用。使用AMPERSAND(&)操作员明确地采用数组的地址,同时省略AMPERS,从而使其隐式接收数组的地址。最后,结果是相同的。
更重要的是,直接在字段上使用sizeof是更容易且易于错误的:
std::memcpy(msg2.data, msg1.data, sizeof(msg1.data));
避免错别字,更重要的是,如果字段更改大小,则不必浏览您使用的代码。
至于data2,zwol在下面的答案中是正确的,因为它取决于数据的确切存储方式 - 或更准确地说,谁拥有" data2以及如何释放变量。您可能想研究"浅"与"深"复制。
您的最后两个memcpy()
S应该是sizeof(msg1.data)
不是100*sizeof(unsigned int)
-无论如何它们是unsigned char
S!
但最后一个:
memcpy(msg2.data, msg2.data, 100*sizeof(unsigned int));
是正确的。如果要使用早期的,请使用:
memcpy(&msg2.data[0], &msg1.data[0], 100*sizeof(unsigned int));
它们两个都是错误的,因为如果sizeof(unsigned int)
大于sizeof(char)
,它们将导致范围访问。
您可以做一个
之一memcpy(&msg2.data, &msg1.data, sizeof(msg1.data)); // pass pointers to arrays
memcpy(msg2.data, msg1.data, 100*sizeof(unsigned char)); // pass pointers to first elements of the arrays
表达式msg.data
的类型与表达式&msg.data
的类型不同,但是 values 是相同的。由于这是C ,因此在[conv.ptr]/2
中非常清楚地指定了该行为:memcpy
的调用导致两个指针参数向[const] void *
的隐式转换,并且此转换的结果"指向对象属于对象的开始,如该对象所在的位置的开始如果它是最派生的对象(而不是基类子对象)"。(在C中,效果是相同的,但是标准人对这样说的不太清楚 - 您必须读取C99第6.3.2.3节第1段和第7段,并理解memcpy
行为的行为一样,就好像它将其论点转换为Pointers-内部类型。)
data
被声明为
unsigned char data[100];
因此,以下所有内容都是等效的。他们中的第一个将是我从事过的大多数代码库中的首选样式。
memcpy(msg2.data, msg1.data, sizeof msg1.data);
memcpy(msg2.data, msg1.data, 100);
memcpy(msg2.data, msg1.data, 100 * sizeof(unsigned char));
memcpy(&msg2.data, &msg1.data, sizeof msg1.data);
memcpy(&msg2.data, &msg1.data, 100);
memcpy(&msg2.data, &msg1.data, 100 * sizeof(unsigned char));
但是,
memcpy(msg2.data, msg1.data, 100 * sizeof(unsigned int));
是错误的;它复制了太多的内存。这就是为什么具有sizeof
的表格是首选样式的原因;首先,很难犯错,并且如果更改类型的定义,就不会默默成为错误。图
也是一种风格,我更喜欢在这种情况下不编写&
,因为&[anything with an array type]
几乎总是错误的,因此除非实际是必要的,否则不应以这种方式写。
您应该知道sizeof(any sort of char) == 1
按定义(C [Expr.SizeOf]/1)。这是我个人但广泛共享的观点,即这意味着sizeof(char)
绝不应该出现在您的代码中。
最后,我无法告诉您没有更多信息的正确方法复制data2
。我需要知道data2
点是什么,分配方式以及是否应复制或引用。
¹除非在sizeof(unsigned char) == sizeof(unsigned int)
的不太可能情况下;在原始的瓦里(Cray)上是正确的,标准仍然允许这种可能性,但是Afaik没有实施者实际上在很多年中做到了这一点。
²反驳:这将sizeof
应用于阵列类型,这是有风险的,因为阵列类型"衰减"到指针类型的情况下,如果给出了丝毫的机会,则会再次默默错误。但是,如果您是手工复制结构成员的情况 - 我认为它比替代方案不那么危险。
- 从结构寻址时,MMAP变量的行为很奇怪
- 访问在 C++ 结构中声明的枚举变量
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 如何为 c++ 的不同变量类型的结构元素创建动态数组?
- 为什么未命名的结构内联变量在每个翻译单元中没有相同的地址?
- 在类构造函数中使用结构变量
- 在 c++ 中将变量作为结构构造函数中的引用传递
- 在类构造函数中定义结构变量的参数
- 为什么我们再次从结构对象创建结构变量?
- 从另一个 cpp 文件更改结构内、映射键内的变量
- 模板化结构中的零大小成员变量
- C++ 结构中的可选变量(变量结构)
- 对其中一个变量的多变量结构进行排序
- 指向非指针变量结构的指针。这些变量在哪里,堆还是堆栈?
- 是好是坏:为了避免使用全局变量/结构体的属性/大量参数而使用巨型结构体
- Cpp变量/结构用于存储128位数据
- 第一私有变量结构中允许的OpenMP调用和指令
- VS2008传递变量-结构与结构组件-优点/缺点
- 在c++类成员函数中使用c库变量/结构成员
- 如何不迷失在执行'<'对于多变量结构