数组元素指针:
一个变量有地址,一个数组包含若干个元素,每个数组元素都有相对应的地址,指针变量可以指向数组元素(把某一元素的地址放到一个指针变量中)所谓数组元素的指针就是数组元素的地址。
可以用一个指针变量指向一个数组元素。
int a[10]={1,3,5,7,9,11,13,15,17,19};
int *p;
p=&a[0];
等价于int *p=a;
或int *p=&a[0];
等价于p=a;
注意:数组名a不带表整个数组,只代表数组首元素的地址。
"p=a;"的作用是"吧a数组的首元素的地址赋给指针变量p",而不是"把数组a各个元素的值赋给p"
2)数组指针初始化和使用方法
a、使用指针引用数组元素
在指针指向元素时,允许一下运算:
加一个整数(用+或+=),如p+1
减一个整数(用-或-=),如p-1
自加运算,如p++,++p
自减运算,如p--,--p
两个指针想减,如p1-p2(只有p1和p2都指向同一数组中的元素时才有意义 )
b、注意;如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址,或者说,它们指向a数组序号为i的元素。
①数组指针的作用:使用数组指针间接访问数组的元素。
②数组指针的定义:int *p;
③数组指针的初始化:int a[4]={1,2,3,4};
int *p=a;//数组指针,定义了一个指针变量p指向数组a的首地址(也是第一个元素a[0]的首地址),p指向数组的第一个元素
等价于:
int *p=&a[0];
④数组指针如何访问数组的元素:
a)p+1 表示指向数组的下一个元素
b)p-1 表示指向数组的上一个元素
④结论:
引用一个数组元素,可用下面两种方法:
a)下标法:如a[i]的形式
b)指针法:如*(a+i)或*(p+i)
c)a是常量(a++错误),p是变量(p++正确) ,,
⑤总结:对于一个一维数组来说
A)获取a[i]的地址方法:
a)&a[i];//直接取地址
b)a+i;
c)p+i;
B)获取a[i]的值的方法:
a)a[i];
b)*(a+i);
c)*(p+i);
d)*(&a[i]);
3)应用:逆序数组
思路:
//用指针将数组a中的n个整数按相反顺序存放。
//将a[0]与a[n-1]对换
//注意:a[i]=*(a+i);
代码:
//逆序一个数组
void nixuArray(int a[],int len){
//定义一个数组指针
int *p=a;
//定义下标
int i=0,j=len-1;
int temp;
while(i<j){
//交换a[i]和a[j]
temp=*(p+i);
*(p+i)=*(p+j);
*(p+j)=temp;
//修改下标
i++;
j--;
}
}
void main(){
int arr[10]={1,2,3,4,5,6,7,8,9,10};
//调用函数nixuArray()
nixuArray(arr,10);
for(int i=0;i<10;i++){
printf("%d\t",arr[i]);
}
}
4)一维指针数组
a、一维指针数组
一个数组的元素值为指针则是指针数组。指针数组时一组有序的指针的集合。指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。指针数组说明的一般形式为:
类型说明符 *数组名[数组长度]
其中类型说明符为指针值所指向的变量的类型。
例如:
int *pa[4];
表示pa是一个指针数组,它有四个数组元素,每个元素值都是一个指针,指向整型变量。
b、指针数组的使用:
int a=3,b=4,c=5;
int *pa[3]={&a,&b,&c};
5)指针变量之间的算术运算:只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。
a、两指针变量减法运算
两指针变量想减所得之差是两个指针所指向数组元素之间相差的元素个数。
实际上是两个指针值(地址)想减之差在除以该数组元素长度(字节数)。
b、指针变量之间的算术运算
①两个指针之间的减法运算
常见的用法:两个指针都指向同一个数组
i、判断两个指针变量指向的元素是否连续
ii、判断两个指针变量之间相隔几个元素。
如果两个指针变量指向同一个元素,那么他们想减的结果是0
判断两个指针变量指向的元素是否相邻(连续),他们想减的结果是1的绝对值
②两个指针之间的关系运算
p1>p 返回结果为1则p1在高位
返回结果为0则p在高位或者他们指向了同一个位置
c、注意:两指针之间只有减法运算,没有加、乘、除运算
6)用数组名访问二维数组
a、用数组名访问二维数组
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
a代表第0行首地址 a+1代表第一行首地址 a+2代表第二行首地址
a+i代表行号为i的首行地址(按行变换)。
*(a+1)相当于&a[1][0]
*(a+i)相当于&a[i][0]
列指针:
a[0] ==&a[0][0] //第一列的首地址
a[0]+1==&a[0][1] //第二列的首地址
a[0]+2==&a[0][2] //第三列的首地址
... ...
a[0]+i==&a[0][i] //第i列的首地址
7)二维数组指针定义、初始化
a、二维数组名师指向行的,它不能对如下说明的指针变量p直接赋值:
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,11,12,14}},*p;
其原因就是p与a的对象性质不同,或者说二者不是同一级指针。C语言可以通过定义数组指针的方法,使得一个指针变量与二维数组名具有相同的性质。
b、二维数组指针变量说明的一般形式为:
数据类型 (*指针变量名)[二维数组列数]
其中"类型说明符"为所指数组的数据类型。"*"表示其后的变量时指针类型。
c、如果要将二维数组赋给一指针,则应这样赋值:
int a[3][4];
int (*p)[4];//该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++; //该语句执行过后,也就是p=p+1;p跨过a[0][]指向了行a[1][]
所以数组指针也称指向一维数组的指针,亦称行指针。
d、二维数组指针
行指针,用来指向二维数组的每一行,存放的是行的首地址
定义格式:
数据类型 (*行指针变量名)[数组第二维的长度]
二维数组指针的初始化
int a[2][3];
int b[2][2];
float f1[4][4];
//假设定义一个指向数组a的一个行指针,则写法如下:
//a=&a[0]=&a[0][0]=a[0]
int (*ap)[3]=a;
二维数组指针的使用
*(*(p+i)+j);//就是获取二维数组的每个元素
代码示例:
void main(){
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4]=a;
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
printf("%d\t",*((*p+i)+j));
}
printf("\n");
}
}
//输出结果为:
//1 3 5 7
//9 11 13 15
//17 19 21 23
8)指针数组和二维数组指针的区别
a、指针数组和二维数组指针变量的区别
应该注意指针数组和二维数组指针变量的区别。虽然这两者都可以用来表示二维数组,但是其表示方法和意义是不同的。
二维数组指针变量时单个的变量,其一般形式中"(*指针变量名)"两边的括号不可少。而指针数组类型表示的是多个指针(一组有序指针)在一般形式中"*指针数组名"两边不能有括号。
例如:int (*p)[3];
表示一个指向二维数组的指针变量。该二维数组的列数分为3或分解为一维数组的长度为3.
int *p[3];
表示p是一个指针数组,有三个下标变量p[0],p[1],p[2]均为指针变量。