0

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?

1
  • 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
    Commented Jan 18, 2023 at 6:06

2 Answers 2

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) {.

1
  • 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
    Commented Jan 18, 2023 at 14:10
2

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).

3
  • 3
    However 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
    Commented Jan 18, 2023 at 8:13
  • @KIIV Sure, but the question was about the existing code, I think.
    – PMF
    Commented 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 Juraj
    – Jim Mack
    Commented Jan 18, 2023 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.