数组的使用的注意事项

一. 数组的初始化

  1. for循环初始化
      可以先定义,后初始化 ;
  2. 列表初始化
      定义和初始化必须在一起;结构的初始化也是这样。
int arr[5];
arr[5]={1,2,3,4,5};  // error

int arr[5]={1,2,3,4,5};  //right

二、数组和指针的关系

 首先数组和指针是完全不一样的存在,只是访问形式存在相似。指针是在内存中有一个单元存放着指向某对象的地址;而数组只是可以使用它的数组名当成地址来对数据进行操作。

1. 指针和数组的访问形式

(1)访问指针

  • 以指针的形式 *(p+4)
  • 以下标的形式 p[4]
    p[4]这个操作会被解析成:先取出p里存储的地址值;再加上中括号中4个元素的偏移量,计算出新的地址;然后从新的地址中取出值。

(2)访问数组

  • 以指针的形式 *(a+4)
    a这时候代表的是数组首元素的首地址
  • 以下标的形式 a[4]
    编译器总是把下标的形式的操作解析为以指针的形式的操作。
2.数组名a,则a、&a和&a[0]的区别

 三者的值都是一样的(都是存放数组a的第一个元素的地址)。但是意思不一样。a表示数组首元素的首地址,sizeof(a)等于整个数组的长度,a+1 等于数组中下标为1的元素。&a表示整个数组的最开始的地址,sizeof(a)等于4,即指针的大小;&a+1是下一个数组的首地址,显然当前的指针已经越过了数组的界限。&a[0]就弱化成没有数组类型含义的首元素的地址。

int a[5]={1,2,3,4,5};
int* ptr=(int *)(&a+1);
cout<<a+1<<endl;
cout<<*(ptr+1)<<endl;

第一行输出的是2;
第二行输出的是一个不确定的数,该数是内存中数组下一个4字节强制转行成int类型的数。

三、把数组传给子函数

把数组传递给函数,形参会弱化成指针,而不是数组,所以在传递数组名的时候,还需要传递数组的大小;
此时函数声明有两种

  1. int sum(int *a,int size) 其中 *a强调数值名弱化为指针
  2. int sum(int a[],int size) 其中a[]就是指针的意思,这样更直观的看出传入的参数应该为指针。

对于二维数组:

int data[3][4]={{1,2,3,4,},{9,8,7,6},{2,4,6,8}};
int total=sum(data,3);

为什么将行数3,而不是列数4作为参数呢?
因为行数的头元素代表地址,所以可以讲第一行的第一个元素的地址传入到函数中,就可以对每一个元素进行访问。
此时函数的声明有两种:
3. int sum(int (*a)[4], int size );
4. int sum(int a[][4], int size) ;
其中列数应该显示的表达出来,让编译器知道。

猜你喜欢

转载自blog.csdn.net/qq_34915122/article/details/83279694
今日推荐