Is array order within union data structure is different than the outside array?

Form the results of the following codes, it appears to me that:

(1) Within union data structure, the most significant array element (member) of a two-element array (yArray[2] has been referred by yArray[1].

(2) Outside union data structure, the most significant array element (member) of a two-element array (xArray[2] has been referred by xArray[0].

Is it like this? or I am making a mistake!

Would appreciate clarification.

void setup() 
{
  Serial.begin(9600);

  byte xArray[2] = {0x67, 0x89};

union {
        byte yArray[2];
        int Q;         
      } bcd;

  bcd.Q = 0x6789;

  Serial.print(bcd.Q, HEX);  // shows: 6789
  Serial.print('\n');

  Serial.print (bcd.yArray[0], HEX);        // shows: 89
  Serial.print('\n');

  Serial.print(xArray[1], HEX);             //shows: 89
  Serial.print('\n');

}

void loop() 
{
  

}

Perhaps an Endianness thing since you're assigning a value to an int that happens to occupy the same memory locations as yArray.

Perhaps you do not understand how an int is stored?

Try this:

void setup() 
{
  Serial.begin(9600);

  byte xArray[2] = {0x67, 0x89};

  int* asInt = (int*)xArray;  // lets see your array as an int

  Serial.print(*asInt, HEX);  // should print 0x8967

}

See, what you put in the array is backwards of how the integer would be stored. The difference you saw isn't because it is or isn't in a union, it's because you used an int to initialize one time and you put the bytes in (backwards) yourself when you filled the array outside the union with bytes.

GolamMostafa:
Form the results of the following codes, it appears to me that:

(1) Within union data structure, the most significant array element (member) of a two-element array (yArray[2] has been referred by yArray[1].

(2) Outside union data structure, the most significant array element (member) of a two-element array (xArray[2] has been referred by xArray[0].

Is it like this? or I am making a mistake!

You are confusing concepts.

Array elements are not more or less "significant" than each other, they are all on an equal level. There are higher and lower indexes, but that fact alone does not carry any implications unless you yourself give it meaning in the context of your code. Indexes are merely positions.

The concept of "significance" only arises when multiple bytes are combined to store a single large-value number. In AVRs, 2 bytes are used for an int, 4 bytes for a long int, and 8 bytes for a long long int (Yes, that's actually a thing). Each byte needs a weight, or significance, assigned to it, just like numerals in a written number are assigned weights of 1, 10, 100, 1000, 0.1, etc.

The two common conventions for significance are Big Endian, where the lowest addressed byte is the most significant, and Little Endian, where the lowest addressed byte is the least significant. The AVR-GCC compiler is apparently Little Endian.

It's not the compiler that is Little Endian. It is the processor itself. The compiler generates code suitable for the little-endian AVR processor. I think you can target the compiler at a big-endian processor, in which case it will produce the correct code for that too.
When I compile blink for a NANO, these two defines are included on the avr-g++ compiler's command line by the IDE:

-DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR

The first specifically tells the compiler that it is targeting a NANO and the second specifies that the processor is an AVR architecture which implicitly means that the processor is little-endian.

Pete

It’s not the compiler that is Little Endian. It is the processor itself.

meh. The AVR is pretty “weakly” little-endian, since the only instructions that do more than a single byte move to or from memory are the “call” and “ret.” It’s true that the register addressing for the ADIW and SUBIW instructions (and multiply) is also little-endian, but the registers are so rarely addressed as memory that I’m not sure they count. You could (theoretically) modify avr-gcc to be big-endian, and it wouldn’t be much trouble, or result in any performance reduction.

Quick explanation of “endianness”:
If you have memory that is addressed as a sequence of bytes, and a processor/compiler that can do math on operands that are more than a single byte long, someone has to decide how the multiple bytes are stored in memory. Usually there are two options:

Little-endian: the least significant byte is stored at the smaller address. So 0x12345678 would be stored at 100:78, 101:56, 102:23, 103:12 There is nothing inherently wrong with this, but it “looks wrong” when displayed in most left-to-right, low-address-to-high-address display systems (which is most of them.) This matches the mathematical number of bits (least significant bit is B0, because it is 20

Big-endian: the most significant byte is stored at the smaller address. 0x12345678 becomes 100:12, 101:34, 102:56, 103:78. Matches human expectations better, but few “real” advantages.

See also https://www.ietf.org/rfc/ien/ien137.txt - the argument carries on into bitfield numbering, and transmission order (of both bits and bytes) It mainly comes up when you have to transfer data from one system to another, because otherwise all you need to do is be consistent.

The stack pointer, X,Y,Z indirect addressing registers on the AVR are little endian. I'll bet pointers are too.

Yeah; all the register-pair stuff is little-endian; I did forget that the indirect addressing uses them…
(Pointers are either numbers or indirect addresses, so “of course” they’re little endian, but they’re already covered by the discussion.)

It's because it's a RISC processor that the opcodes are essentially endian agnostic.