I'm unsure how this will be handled by the Arduino compiler. If anyone can explain what and why, I'd appreciate it. This is obviously very simplified, but it does contain the actual issue.
At the module level I have this union
. I understand that this is strictly speaking not correct C++, but it does work for me, at least when used directly and not passed as a argument to a function.
union _TAT { // access as bytes or uint32
uint32_t wide = 0;
uint8_t bytes[4];
};
_TAT oneTAT; // a variable of _TAT
Suppose I also have a function that works on these:
void fix_Term(_TAT atat) {
atat.wide = 0;
atat.bytes[3] = 17;
}
...and I invoke it with:
fix_Term(oneTAT);
As I understand it, passing AnArray[]
is equivalent to passing *AnArray
, so the function might/should see atat.bytes[3]
as a pointer to that byte of the variable. But what about atat.wide
? I haven't explicitly passed oneTAT
by reference, so...?
What might actually happen here? It does compile without complaint but I can't test it because the hardware it depends on isn't available yet. Besides, even if it works, I'd like to know why.
And of course, if it's just wrong, how do I best accomplish passing and modifying a variable like this?
-
you can test your native code in tinkercad's Arduino simulator. Arduino is usually about the same as plain c++, so compiler explorer is another online option.dandavis– dandavis2023年01月18日 06:06:51 +00:00Commented Jan 18, 2023 at 6:06
2 Answers 2
It is confusing in C and C++ that arrays are passed as pointers but an instance of class, struct or union is always passed by value (so as a copy) including the arrays which are part of the memory space of the structure as in the case of your union.
If you want to pass by reference, declare the function's parameter as a reference 'type'. For example void fix_Term(_TAT& atat) {
.
-
Thanks, this seems to be the missing piece for me. I do want to pass by reference but was confused (as you note) by the * / [] .Jim Mack– Jim Mack2023年01月18日 14:10:14 +00:00Commented Jan 18, 2023 at 14:10
Yes passing AnArray[]
is equivalent to passing *AnArray
. But declaring uint8_t *anarray1
is not equivalent to declaring uint8_t anarray2[4]
in a struct/class/union definition. The former includes a pointer to a byte in the struct, the later actually includes 4 bytes in the struct. So in the later case, anarray2
already points to data, and using variable.anarray2[0]
correctly gets you the value in the structure, while calling variable.anarray1[0]
would result in undefined behavior, because the pointer just points anywhere.
So your code is compiling and executing without error, but since you're passing the union by value, the effect of your fix_term
function is discarded, much like if you had passed in an ordinary value type instead (such as int).
-
3However he can pass it by reference:
void fix_Term(_TAT & atat)
+ call is the same and then it'll change the original union variable.KIIV– KIIV2023年01月18日 08:13:43 +00:00Commented Jan 18, 2023 at 8:13 -
@KIIV Sure, but the question was about the existing code, I think.PMF– PMF2023年01月18日 08:21:44 +00:00Commented Jan 18, 2023 at 8:21
-
Yes, the question was about what the original code is doing, but it also solicited advice on making it work. Got it now, I think, thanks to you and JurajJim Mack– Jim Mack2023年01月18日 14:09:56 +00:00Commented Jan 18, 2023 at 14:09