当前位置:   article > 正文

C语言从头学29——数组(二)

C语言从头学29——数组(二)

四、数组的地址(继续前文编号)
       数组是连续有序储存的同类型值,只要获得首地址(第0个成员的内存地址),其它成员的地址也就知道了,就能遍历整个数组。比如,声明一个数组:int arr[5]={1,2,3,4,5}; 又 int* p=&arr[0]; 那么指针p中保存的就是数组 arr 的首地址,故有*p值是1; ( 首个成员的值 )。C语言为简化计,规定数组名等同于数组首地址,即有 *p=arr; 。 如此,把数组名传入一个函数,就等同于传入一个指针变量。在函数内部,就可以通过这个指针变量获得整个数组。
       同理,对于二维甚至多维数组,数组名也是这些数组的首地址。
五、数组指针的加减计算
       仍接上面的例子,p是指向数组 arr 首地址指针,*p的值是1;接下来我们给p加上1,此时 *(p+1) 的值就是2;也就是说,首地址指针加上n则指针就指向第n个成员(注意我们讲地址还有第几个成员均从0开始计),然后用 *(p+n) 就能取出这个地址的值。指针能加也能减,减就是指针指向回退一个成员。十分注意的是指针加减后的结果不能越界。
       由于指针p与数组名arr等价,所以用*(arr+n)来取第n个成员的值也是一样的。
       关于数组的地址及指针加减运算我们用一个例子做说明:

  1. #include<stdio.h>
  2. void myArr(int* arr)
  3. {
  4. int* p = arr; //p指向第0号成员
  5. int temp = *p;
  6. printf("数组arr的第0号成员是:%d\n", temp);
  7. p = p + 4;//p指向了第4号成员
  8. temp = *p;
  9. printf("数组arr的第4号成员是:%d\n", temp);
  10. p = p - 2;//p从4回退2个位置指向2号成员
  11. temp = *p;
  12. printf("数组arr的第2号成员是:%d\n", temp);
  13. }
  14. int main(void)
  15. {
  16. int arr[5] = { 1,2,3,4,5 };
  17. myArr(arr);
  18. printf("-----------------------\n");
  19. printf("数组arr的第2号成员是:%d\n", *(arr + 2)); //用arr替代p进行计算
  20. getchar();
  21. return 0;
  22. }

运行结果:
       数组arr的第0号成员是:1
       数组arr的第4号成员是:5
       数组arr的第2号成员是:3
       -----------------------
       数组arr的第2号成员是:3
六、数组的复制
       数组名字是指针,所以复制数组名字并不是真正的复制数组,而是复制了一个指针,原指针和复制指针共同指向同一个数组,如果原数组消失则复制的数组也不存在了。
       简单的复制方法是利用循环一个成员一个成员的完成复制,具体可看下面代码:

  1. int arr[5] = { 1,2,3,4,5 };
  2. int arrBak[5] = { 0 };
  3. for (int i = 0; i < 5; i++) arrBak[i] = arr[i]; //逐个成员复制
  4. for (int i = 0; i < 5; i++) printf("%d ", arrBak[i]); //显示复制结果

运行结果:1  2  3  4  5(复制完成)
       对于二维或者多维数组,复制需要开双重循环或多重循环。
       还有一种赋值方法,就是调用memcpy() 函数直接把数组所在的那一段内存再复制出一份。memcpy()有3个参数:
     参1 目标数组名 参2 源数组名 参3 目标数组字节长度。见下例:

  1. int arr[5] = { 1,2,3,4,5 };
  2. int arrBak[5];
  3. memcpy(arrBak, arr,sizeof(arrBak)); //完成复制
  4. for (int i = 0; i < 5; i++) printf("%d ", arrBak[i]); //显示复制结果

运行结果:1  2  3  4  5(结果与循环方法相同,函数方法速度快于循环方法)
       说明:由于版本不同,memcpy是否包含在<stdio.h>不能确定,如报错请包含<string.h>。
七、数组作为函数的参数
       1. 数组作为函数的参数,一般会同时传入数组名和数组成员数。由于数组名是一个指针,如果只传数组名,那么函数
只知道数组开始的地址,不知道有几个成员。如果函数的参数是多维数组,那么除了第一维的成员数可以当作参数传入函数,
其他维的成员数需要写入函数参数声明。()
      2.数组字面量作为函数参数,直接将数组字面量传入函数。方法是带有大括号的数组各成员的值直接放到参数名的位置,后边再跟上数组成员数这个参数;然后在大括号前面一对小括号,括号里是函数数组参数声明(但把数组名去掉)。这种方式类似于用数组类型对传入的字面量(数组成员值)进行强转,让编译器明白这组值的类型。
       以上两项,特别是第2项用语言表达不是很明白,还是放到下面的例子中进一步说明,代码如下:

  1. #include<stdio.h>
  2. int mySum(int a[][5], int n)
  3. {
  4. int sum = 0;
  5. for (int i = 0; i < n; i++)
  6. {
  7. for (int j = 0; j < 5; j++)
  8. {
  9. sum += a[i][j];
  10. }
  11. }
  12. return sum;
  13. }
  14. int main(void)
  15. {
  16. int arr[2][5] = { {1, 2, 3, 4, 5},{6, 7, 8, 9, 10} };
  17. int sum=mySum(arr, 2); //传入数组名及第一维成员数
  18. printf("%d\n", sum); //运算结果:55
  19. sum = mySum((int[][5]) { {1, 2, 3, 4, 5}, { 6, 7, 8, 9, 10 } }, 2);
  20. //将数组字面量直接及第一维成员数直接传入函数,注意(int[][5])中无数组名,只剩类型
  21. printf("%d\n", sum);//运算结果:55
  22. getchar();
  23. return 0;
  24. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/799226
推荐阅读
相关标签
  

闽ICP备14008679号