数组

最近看了一些关于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

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值