Ok - so I'll preface this by saying I'm not entirely sure how to describe the question and my current confusion, so I'll do my best to provide examples.
Question
Which of the two approaches to using the typedef-ed, fixed-length array in a memcpy call (shown below in "Context") is correct? Or are they equivalent?
(I'm starting the think that they are equivalent - some experimentation under "Notes", below).
Context
Consider the following typedef typedef uint8_t msgdata[150];
and the library interface const msgdata* IRead_GetMsgData (void);
.
In my code, I use IRead_GetMsgData and memcpy the result into another uint8_t buffer (contrived example below).
//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));
}
}
Now, this works and passes our unit tests fine but it started a discussion between our team about whether we should dereference myData in this case. It turns out, not dereferencing myData also works and passes all our unit tests
std::memcpy(mBuff, myData, sizeof(msgdata)); //This works fine, too
My thought when writing the memcpy call was that, because myData is of type msgdata*, dereferencing it would return the pointed-to msgdata, which is a uint8_t array. E.g.
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]
I've tried searching for discussion of similar questions but haven't yet found anything that felt relevant:
- Using new with fixed length array typedef - how to use/format a typedef
- How to dereference typedef array pointer properly? - how to dereference a typedef-ed array and access its elements
- typedef fixed length array - again how to format the typedef.
The last one in that list felt most relevant to me, as the accepted answer nicely states (emphasis mine)
[this form of typedef is] probably a very bad idea
Which, having now tried to understand what's actually going on, I couldn't agree with more! Not least because it hides the type you're actually trying to work with...
Notes
So after we started thinking on this, I did a bit of experimentation:
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
And if I extend that to include a suitable array, arr
and a defined size value, size
, I can use various memcpy calls such as
std::memcpy(arr, data, size);
std::memcpy(arr, pData, size);
std::memcpy(arr, *pData, size);
Which all behave the same, leading me to believe they are equivalent.
I understand the first and last versions (data
and *pData
), but I'm still unsure of what is happening regarding the pData
version...