int arr[] = { 99, 15, 100, 888, 252 };
为例,该数组在内存中的分布如下图所示:
定义数组时,要给出数组名和数组长度,数组名可以认为是一个指针,它指向数组的第 0 个元素。在C语言中,我们将第 0 个元素的地址称为数组的首地址。以上面的数组为例,下图是 arr 的指向:
数组名的本意是表示整个数组,也就是表示多份数据的集合,但在使用过程中经常会转换为指向数组第 0 个元素的指针,所以上面使用了“认为”一词,表示数组名和数组首地址并不总是等价。初学者可以暂时忽略这个细节,把数组名当做指向第 0 个元素的指针使用即可,我们将在VIP教程《数组和指针绝不等价,数组是另外一种类型》和《数组到底在什么时候会转换为指针》中再深入讨论这一细节。下面的例子演示了如何以指针的方式遍历数组元素:
#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int len = sizeof(arr) / sizeof(int); //求数组长度 int i; for(i=0; i<len; i++){ printf("%d ", *(arr+i) ); //*(arr+i)等价于arr[i] } printf("\n"); return 0; }运行结果:
*(arr+i)
这个表达式,arr 是数组名,指向数组的第 0 个元素,表示数组首地址, arr+i 指向数组的第 i 个元素,*(arr+i) 表示取第 i 个元素的数据,它等价于 arr[i]。
arr 是int*
类型的指针,每次加 1 时它自身的值会增加 sizeof(int),加 i 时自身的值会增加 sizeof(int) * i,这在《C语言指针变量的运算》中已经进行了详细讲解。
我们也可以定义一个指向数组的指针,例如:
int arr[] = { 99, 15, 100, 888, 252 }; int *p = arr;arr 本身就是一个指针,可以直接赋值给指针变量 p。arr 是数组第 0 个元素的地址,所以
int *p = arr;
也可以写作int *p = &arr[0];
。也就是说,arr、p、&arr[0] 这三种写法都是等价的,它们都指向数组第 0 个元素,或者说指向数组的开头。
再强调一遍,“arr 本身就是一个指针”这种表述并不准确,严格来说应该是“arr 被转换成了一个指针”。这里请大家先忽略这个细节,我们将在VIP教程《数组和指针绝不等价,数组是另外一种类型》和《数组到底在什么时候会转换为指针》中深入讨论。如果一个指针指向了数组,我们就称它为数组指针(Array Pointer)。
int *
。#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int i, *p = arr, len = sizeof(arr) / sizeof(int); for(i=0; i<len; i++){ printf("%d ", *(p+i) ); } printf("\n"); return 0; }数组在内存中只是数组元素的简单排列,没有开始和结束标志,在求数组的长度时不能使用
sizeof(p) / sizeof(int)
,因为 p 只是一个指向 int 类型的指针,编译器并不知道它指向的到底是一个整数还是一系列整数(数组),所以 sizeof(p) 求得的是 p 这个指针变量本身所占用的字节数,而不是整个数组占用的字节数。#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int *p = &arr[2]; //也可以写作 int *p = arr + 2; printf("%d, %d, %d, %d, %d\n", *(p-2), *(p-1), *p, *(p+1), *(p+2) ); return 0; }运行结果:
#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int i, *p = arr, len = sizeof(arr) / sizeof(int); for(i=0; i<len; i++){ printf("%d ", *p++ ); } printf("\n"); return 0; }运行结果:
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有