vì trình biên dịch có quyền sắp xếp lại biến nằm trên stack tùy ý, ở đây là x, y, u, v, a. Có thể là a,x,y,u,v hoặc u,a,v,y,x v.v… nên nó ko theo thứ tự x,y,a,u,v đâu mà mong a[-1] = y hay a[5] = u.
mà dù có xếp là x,y,a,u,v thì truy cập a[-1] và a[5] cũng là undefined behavior :V đừng mong a[-1] là y hay a[5] là u :V vì chỉ có a[0]…a[4] là bảo đảm liên tục, còn x,y,u,v nằm rải rác tùy ý cách nhau 100 bytes cũng được :V
trong C++ struct tuy bảo đảm thứ tự nhưng viết kiểu này cũng là undefined behavior:
struct S { // bảo đảm thứ tự x, y, a, u, v
int x = 11;
int y = 12;
int a[5] = {21, 22, 23, 24, 25};
int u = 31;
int v = 32;
};
// a[0] .. a[4] hợp lệ
// a[-1], a[-2] là undefined behavior mặc dù liền trước nó là y, x
// a[5], a[6] là undefined behavior mặc dù liền sau nó là u, v
trong C (ko phải C++) có thể xài union cast
union U {
struct S { // bảo đảm thứ tự x, y, a, u, v
int x;
int y;
int a[5];
int u;
int v;
} s;
int arr[9];
};
// u.arr[0] === u.s.x, u.arr[1] === u.s.y
// u.arr[2] === u.s.a[0], ...
// u.arr[7] ==== u.s.u, u.arr[8] === u.s.v
trong C++ thì KHÔNG làm vậy được :V Vì https://www.youtube.com/watch?t=2972&v=IAdLwUXRUvg&feature=youtu.be trong C++ array và struct ko có common initial sequence :V :V :V
C++ (và C) có thể xài memcpy
struct S { // bảo đảm thứ tự x, y, a, u, v
int x = 11;
int y = 12;
int a[5] = {21, 22, 23, 24, 25};
int u = 31;
int v = 32;
} s;
int arr[9];
memcpy((void*)arr, &s, sizeof arr);
int* a = arr + 2; // a là con trỏ
// a[-2] === arr[0] === s.x, a[-1] === arr[1] === s.y
// a[0] === arr[2] === s.a[0], ...
// a[5] === arr[7] ==== s.u, a[6] === arr[8] === s.v
đừng sợ memcpy làm chậm chương trình vì phải copy ra biến tạm, khi optimize trình dịch sẽ tự cast s
thành arr
luôn mà ko cần copy ra biến tạm :V Nếu muốn modify s.x = 12
thông qua arr[0] = 12
thì xài thêm 1 lần memcpy arr
vào s
nữa, nó cũng sẽ optimize ko copy ra biến tạm mà set thẳng vào s
luôn :V