数组一旦被定义,数组元素将在内存中占用一块连续的内存单元,数组名就是这块连续内存单元的起始地址。
写一个简单的例子。
#include "stdio.h"
int main() {
int *p = 0, a[5] = {1111, 2222, 3333, 4444, 5555};
p = a; //指针起始地址指向a[0]
printf("-%d\n", *a);//相当于a[0]
printf("--%d\n", *(a + 2));//相当于a[2]
printf("---%d\n", *p); //相当于a[0]
printf("----%d\n", *++p); //相当于a[1]
printf("-----%d\n", p[1]); //相当于a[2]
p = &a[3]; //指针起始地址指向a[3]
printf("------%d\n", *p); //相当于a[3]
printf("-------%d", *(p + 1)); //相当于a[4]
return 0;
}
输出结果。
从上述代码与程序中不难看出,指针可与整型相加减,如p=p+n是将p后移n个基元素的长度,即:
p的地址值±n*sizeof(数据类型)
指针运算符*与++、--的优先级相同,结合方向。
二维数组a到的地址及元素表示形式和含义
表示形式 | 含义 |
a=&a[0] | 二维数组名,数组起始地址,是第0行起始地址,指向一维数组a[0] |
a[0]=*(a+0)=*a=&a[0][0] | 第0行第0列元素的地址 |
a[i]=*(a+i)=&a[i][0] | 第i行第0列元素的地址 |
a+i=&a[i] | 第i行的起始地址 |
a[i]+j=*(a+i)+j=&a[i][j] | 第i行第j列元素的地址 |
*(a[i]+j)=*(*(a+i)+j)==*(&a[0][0]+i*n+j)=a[i][j] | 第i行第j列元素的值 |
C语言中,字符串是一种特殊的字符型一维数组。可以有两种方法访问字符串:一是把字符串中的字符作为数组元素访问;二是利用字符型指针进行访问。
用字符指针可以指向字符变量,也可以指向字符串,通过指针访问字符串中的每个字符。
写一个简单的例子。
#include "stdio.h"
int main() {
char *p1, *p2 = "Hello world!";
p1 = "This is C."; //这里展示两种字符型指针初始化的方法
int i = 0, j = 0;
while (*p1 != '\0') { //判断*p1的值是否是字符串结束符'\0'
i++;
p1++; //指针p1不断下移,遍历整个字符串
}
printf("%s\n", p1 - i); //p1 - i是p1回到字符串起始地址
printf("%s", p2 + 2); //p2的起始地址下移2
return 0;
}
输出结果。
指针数组:数组可以是任何类型,若数组中的每个数组元素都是指针类型,用于存放内存地址,则这个数组就是指针数组。定义指针数组的一般形式如下:
类型说明符 *指针数组名[数组长度]
二级指针:用指向指针的指针变量存放指针变量的地址,这个指针变量称为指向指针的指针,也称为二级指针。定义二级指针的变量的一般形式如下:
类型说明符 **指针变量名
写一个简单的例子。
#include "stdio.h"
int main() {
int *p[3] = {}, a[3] = {0, 1, 2};
int **pp = 0, i = 0;
for (; i < 3; i++)
p[i] = a + i; //指针数组 p 元素获取数组 a 不同元素地址
pp = &p[1]; //二级指针 pp 获取指针数组 p 中元素 p[i] 地址
printf("这是数组元素p[2]指向数组a的元素,其值为%d\n", *p[2]);
printf("这是二级指针pp间接指向的元素,其值是%d\n", **pp);
printf("指针数组元素p[1]地址%x\n", p[1]);
printf("二级指针pp获取到的地址%x\n", *pp);
printf("二级指针pp地址%x", pp);
return 0;
}
输出结果。