好的-因此,我将首先说我不确定如何描述这个问题以及我目前的困惑,以此作为开头。因此,我将尽力提供示例。
题
在memcpy调用中使用类型定义的定长数组的两种方法中的哪一种是正确的?还是等价的?
(我开始认为它们是等效的-在下面的“注释”下进行一些实验)。
语境
考虑以下typedef typedef uint8_t msgdata[150];
和库接口(interface)const msgdata* IRead_GetMsgData (void);
。
在我的代码中,我使用IRead_GetMsgData并将结果memcpy存入另一个uint8_t缓冲区(下面的示例)。
//Included from library:
//typedef uint8_t msgdata[150];
//const msgdata* IRead_GetMsgData (void);
uint8_t mBuff[2048];
void Foo() {
const msgdata* myData = IRead_GetMsgData();
if(myData != nullptr) {
std::memcpy(mBuff, *myData, sizeof(msgdata));
}
}
现在,该方法可以正常工作并通过了单元测试,但在我们的团队之间开始了关于在这种情况下是否应取消引用myData的讨论。事实证明,不取消引用myData也是可行的,并通过了我们所有的单元测试 std::memcpy(mBuff, myData, sizeof(msgdata)); //This works fine, too
编写memcpy调用时,我的想法是,因为myData的类型为msgdata *,对其取消引用将返回指向的msgdata,即uint8_t数组。例如。
typedef uint8 msgdata[150];
msgdata mData = {0u};
msgdata* pData = &mData;
memcpy(somePtr, pData, size); //Would expect this to fail - pData isn't the buffer mData.
memcpy(somePtr, *pData, size); //Would expect this to work - dereferencing pData returns the buffer mData
memcpy(somePtr, mData, size); //Would expect this to work - mData is the buffer, mData ==&mData[0]
我尝试过搜索类似问题的讨论,但还没有发现任何相关的内容:该列表中的最后一个与我最相关,因为公认的答案很好地说明了我(强调我的意思)
现在,我试图理解实际发生的事情,但是我对此表示同意!尤其重要的是,它隐藏了您实际尝试使用的类型...
笔记
因此,在我们开始对此进行思考之后,我做了一些实验:
typedef uint8_t msgdata[150];
msgdata data = {0};
msgdata* pData = &data;
int main() {
printf("%p\n", pData);
printf("%p\n", *pData);
printf("%p\n", &data);
printf("%p\n", data);
return 0;
}
Outputs:
0x6020a0
0x6020a0
0x6020a0
0x6020a0
而且,如果我将其扩展为包括合适的数组arr
和定义的大小值size
,则可以使用各种memcpy调用,例如 std::memcpy(arr, data, size);
std::memcpy(arr, pData, size);
std::memcpy(arr, *pData, size);
它们的行为都一样,使我相信它们是等效的。我了解第一个和最后一个版本(
data
和*pData
),但是我仍然不确定pData
版本正在发生什么... 最佳答案
IMO,此代码是完全错误的。我也将接受另一种观点,即“代码非常容易引起误解”
//Included from library:
//typedef uint8_t msgdata[150];
//const msgdata* IRead_GetMsgData (void);
uint8_t mBuff[2048];
void Foo() {
const msgdata* myData = IRead_GetMsgData();
if(myData != nullptr) {
std::memcpy(mBuff, *myData, sizeof(msgdata));
}
}
取消引用*myData
时,会误导读者。显然,memcpy需要一个指向msgdata
的指针,因此不需要解引用星号。 myData
已经是一个指针。引入额外的取消引用将破坏代码。但这不是...为什么?
这就是您特定用例的地方。
typedef uint8_t msgdata[150];
msgdata是一个衰减为指针的数组。因此,*msgdata
是数组,并且数组是(衰减到)指向其开头的指针。因此,您可能会争辩:没什么大不了的,我可以保留多余的
*
,对吗?没有。
因为总有一天,有人会将代码更改为:
class msgdata
{
int something_super_useful;
uint8_t msgdata[150];
};
在这种情况下,编译器将捕获它,但是通常来说,间接级别错误可能会编译为细微的崩溃。找到无关的*
可能需要您花费数小时或数天的时间。关于c++ - 使用指向typedef固定长度数组的指针执行memcpy时是否需要取消引用?为什么或者为什么不?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63364253/