gpt4 book ai didi

c++ - 使用指向 typedef 固定长度数组的指针执行 memcpy 时是否需要取消引用?为什么或者为什么不?

转载 作者:行者123 更新时间:2023-12-01 14:47:05 26 4
gpt4 key购买 nike

好的 - 所以我会先说我不完全确定如何描述这个问题和我目前的困惑,所以我会尽力提供示例。

问题

在 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]

我已经尝试搜索类似问题的讨论,但还没有找到任何相关的内容:

该列表中的最后一个与我最相关,因为接受的答案很好地说明了(强调我的)

[this form of typedef is] probably a very bad idea

在尝试了解实际情况后,我完全同意!尤其是因为它隐藏了您实际尝试使用的类型...

注意事项

所以在我们开始思考这个问题之后,我做了一些实验:

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 版本发生了什么。 ..

最佳答案

在我看来,这段代码是完全错误的。我也接受另一种观点“代码非常具有误导性”

//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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com