數組

最近看了一些關於C/C++語言中數組的資料,發現以前的理解確有不妥。所謂數組並不是簡單的元素陣列,而是一種數據類型或數據結構。數組名也並不是簡單的常量指針,是一個數組類型的變量,其值爲數組中第一個元素的地址。

int a[2][2][3]={{{10,6,3},{5,4,15}},{{3,5,33},{23,12,7}}};

typeof(a) b = {0}; // 說明a是一種不同於普通指針的數據類型,見sizeof輸出

printf("sizeof(a): %d/n", sizeof(a)); // 48 = 12 * sizeof(int)

printf("sizeof(b): %d/n", sizeof(b)); // 48 = 12 * sizeof(int)

 

數組和指針的對應關係:

  int *p1 = a; // error

  int **p2 = a; // error

  int ***p3 = a; // error

  int (*p4)[2][3] = a; // OK

  printf("sizeof(p4): %d/n", sizeof(p4)); // 4, 指針大小

  printf("0x%p/n", a);     // 0x0022FF30, 數組首地址

  printf("0x%p/n", &a);    // 0x0022FF30, 數組首地址, 和指針變量有區別

  printf("0x%p/n", p4);    // 0x0022FF30, 數組首地址

  printf("0x%p/n", &p4);   // 0x0022FEFC, p4自身的地址

  printf("0x%p/n", *p4);   // 0x0022FF30, 數組首地址

  printf("0x%p/n", **p4);  // 0x0022FF30, 數組首地址

  printf("0x%p/n", ***p4); // 0x0000000A, a[0][0][0]的值

 

數組類型和指針類型的對應關係可總結爲:

ElemType a[M][N][O]…[X][Y][Z] ↔ ElemType (*pa)[N][O]…[X][Y][Z]

多維數組的使用必須遵循這個等價關係才能做到類型安全。

 

多維數組的動態分配:

  int *p5 = new int[10]; // OK

  int *p6 = new int[8][10]; // error

  int **p7 = new int[8][10]; // error

  int (*p8) [10] = new int[8][10]; // OK, 如果語言支持“int[10] (*p8)”則更好理解

 

數組的不同訪問方法(這裏不討論常用的用“[]”訪問元素的方法):

  int i,j,k;

 

  for (i=0;i<2;i++)

    for (j=0; j<2; j++)

      for (k=0; k<3; k++)

        printf("%d ", *(*(*(a+i)+j)+k));

  printf("/n");

 

  for (i=0;i<2;i++)

    for (j=0; j<2; j++)

      for (k=0; k<3; k++)

        printf("%d ", *(**a + i*2*3 + j*3 + k));

  printf("/n");

 

  for (i=0; i<2; i++)

    for (j=0; j<6; j++)

      printf("%d ", *(**(a+i)+j));

  printf("/n");

 

  for (i=0; i<2; i++)

    for (j=0; j<6; j++)

      printf("%d ", *(**a + i*2*3 + j));

  printf("/n");

 

  for (i=0; i<12; i++)

    printf("%d ", *(**a+i));

  printf("/n");

 

對於一個二維數組int array[m][n]而言以下4中表達方法是等價的。

array[i][j]

*(array[i]+j)

(*(array+i))[j]

*(*(array+i)+j)

 

數組名作爲函數的參數:

// array退化爲int *arrayarray是一個指針

// C/C++把數組傳遞改寫爲指針傳遞的主要原因有:

// 1 數組在內存中是連續字節存放的,編譯器可以通過地址計算來引用數組中的元素

// 2 出於性能考慮,如果把整個數組的元素全部傳遞進去,不僅需要大量時間來拷貝數組,拷貝操作還會佔用

//     大量的棧空間

// 從後面的輸出可以看出arrayarray+1相差4,即sizeof(int)

void func1(int array[], int size)

{

    printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);

}

 

void func2(int *array, int size)

{

    printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);

}

 

// array退化爲int (*array)[10] array是一個指針

// 向函數傳遞多維數組時不需要說明第一維的大小而必須說明其他所有維的大小,主要原因有:

// 1) 數組在內存中按照“行優先”規則存儲,所以需要列數來確定一行有多少個元素

// 2) 編譯器在計算元素的地址時不需要數組第一維的長度,但是需要其他維的長度信息

// 3) C/C++不對數組進行越界訪問檢查,因此對編譯器來說不需要知道第一維的長度

// 從後面的輸出可以看出arrayarray+1相差40

// 這說明array並不是一個普通的指針,它指向的數據類型大小爲40,即10*sizeof(int)

void func3(int array[][10], int line)

{

    printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);

}

 

void func4(int (*array)[10], int line)

{

    printf("sizeof(array): %d, 0x%p, 0x%p/n", sizeof(array), array, array+1);

}

 

  int array1[10];

  int array2[8][10];

  func1(array1, 10); // sizeof(array): 4, 0x0022FEB0, 0x0022FEB4

  func2(array1, 10); // sizeof(array): 4, 0x0022FEB0, 0x0022FEB4

  func3(array2,  8); // sizeof(array): 4, 0x0022FD70, 0x0022FD98

  func4(array2,  8); // sizeof(array): 4, 0x0022FD70, 0x0022FD98

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章