Hỏi về kết quả của đoạn code in phần tử trong mảng

Tại sao kết quả a[5]=31, a[6]=32; trong khi a[-2] và a[-1] bằng 0 ạ?

#include <iostream>
using namespace std;
int x = 11;
int y = 12;
int a[5] = {21, 22, 23, 24, 25};
int u = 31;
int v = 32;

int main()
{
	for (int i = -2; i < 7; i++)
		cout << i << " " << a[i] << endl;

}
1 Like

Mình xin giải thích phần a[-1]a[-2] bằng 0: Đó là vì bạn không thể “đi vào lòng đất” trong các array của C++. Khá chắc bạn vừa từ Python sang.

4 Likes

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

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?