-
数组指针:用一个指针变量指向一个数组元素,就是数组指针
作用:使用数组指针间接访问数组元素
注意:(1)数组名a不代表整个数组,值代表数组首元素的地址
(2)”p=a“的作用是”把a数组的首元素的地址赋给指针变量p“。而不是”把数组a各元素的值赋值给p“
2. 在指针指向数组元素时,允许进行以下运算:
+或+=,
-或-=,
自加,
自减,
两个指针相减(只有p1和p2都指向同一数组中的元素时才有意义)
-
数组指针的初始化:
int a[4]={1,2,3,4};
int *p = a; //数组指针,定义了一个指针变量p赋值数组的首地址(第一个元素的地址),p指向数组的第一个元素
int *p = &a[0]; //等价上面一句话
数组指针如何访问数组的元素:
1)p+1 表示指向数组的下一个元素
2)p-1 指向数组的上一个元素
注意:数组名a是一个常量,数组名 a是一个常量相当于 *(10++)这是错误的
//printf(" *a++ =%d\n",*a++); //错误的
-
结论:引用一个数组元素,可用下面两种方法:
-
下标法,如a[i]形式
-
指针法,如*(a+i)或*(p+i)
-
a是常量(a++错误),p是变量(p++正确)
4. 指针数组:
存放指针的数组,就是指针数组
指针数组的定义:
数据类型 * 数组名[数组长度];
int *pa[3];
//定义了一个指针数组,数组名是pa,可以用来存放3个指针(必须是int类型变量的指针)
指针数组的使用:
int a=3,b=4,c=5;
int *pa[3]={&a,&b,&c};
pa[0] a的地址
pa 数组首地址,又是变量a的地址
5. 两个指针变量之间的运算
1)两个指针之间的减法运算:两指针变量相减所得只差是两个指针所指数组元素之间相差的元素个数。
(1)0x0006 - 0x0003 = 3 (意义不大)
(2)常见的用法:两个指针都指向同一个数组
i.判断两个指针变量指向的元素是否连续
ii.判断两个指针变量之间相隔几个元素
地址差值(p1-p)*sizeof(int)
int a[5]={1,2,3,4,5};
int *p = a; //p指向了数组的第一个元素
int *p1 = &a[3]; //p指向了数组的第四个元素
注意:两个指针变量之间没有加法运算
如果两个指针变量指向同一个元素 那么他们相减的结果是 0
判断两个指针变量指向的元素是否相邻(连续),他们相减的结果是 1的绝对值
2)两个指针之间的关系运算
p1 > p
//1 表示p1在高位
//0 p在高位或者他们指向了同一个位置
6. 数组名访问二维数组
#include <stdio.h>
int main(int argc, const char *argv[]) {
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
//列指针
//a[0] == &[0][0] a[0]+1==&a[0][1] a[0]+2==&a[0][2]
printf("&a[0][1] = %p\n",&a[0][1]);
printf("a[0]+1 =%p\n",a[0]+1);
printf("*(a[0]+1) =%d\n",*(a[0]+1)); //3
printf("&a[0][2] = %p\n",&a[0][2]);
printf("a[0]+2 =%p\n",a[0]+2);
//行指针 a[0] a[1] a[2]
//a+1 //第二行的首地址
//a+2 //第三行的首地址
printf("a[1] =%p\n",a[1]);
printf("a+1 =%p\n",a+1);
printf("a[2] =%p\n",a[2]);
printf("a+2 =%p\n",a+2);
// a+1 第二行第一个元素的地址
//*(a+1) == &a[1][0]
printf("*(a+1) = %p\n",*(a+1));
printf("&a[1][0] = %p\n",&a[1][0]);
//a[i]+j 获取的&a[i][j]
//*(a[i]+j) 获取 a[i][j]
//a[i] *(a+i)
//*(*(a+i)+j); -----> a[i][j]
for (int i=0; i<3; i++) {
for (int j=0; j<4; j++) {
//a[i] *(a+i)
//printf("%d\t",*(a[i]+j));
printf("%d\t",*(*(a+i)+j));
}
printf("\n");
}
return 0;
}
7. 数组指针:
定义一个指针变量,让这个指针变量指向一维数组的元素
二维数组指针
行指针,用来指向二维数组的每一行,存放的是行的首地址
定义格式: 数据类型 (*行指针变量名)[数组第二维的长度];
二维数组指针的初始化
int a[2][3];
int b[2][2];
float f1[4][4];
//假设我要定义一个指向数组a的一个行指针
// a = &a[0] = &a[0][0] = a[0]
int (*p)[3] = a;
二维数组指针的使用
*(*(p+i)+j) //就是获取二维数组的每个元素
8.指针数组和二维数组指针变量的区别:
二维数组指针变量是单个变量,其一般形式中“(*指针变量名)”两边的括号不可少。而指针数组类型表示的是多个指针(一组有序指针)在一般形式中“*指针数组名”两边不能有括号。例如:
Int(*p)[3];
表示一个指向二维数组的指针变量。该二维数组的列数为3或分解为一维数组的长度为3.
Int *p[3]
表示p是一个指针数组,有三个下标变量p[0], p[1], p[2],均为指针变量
9. 字符串指针:
定义: char *字符串指针变量名 ="字符串内容";
用作:用来保存一个字符串
注意:1)字符串指针变量的定义说明与指向字符变量的指针变量说明是相同的,只能按对指针变量的赋值不同来区别。对指向字符变量的指针变量应赋予该字符变量的地址。
2)使用字符数组来保存的字符串是保存栈里的,保存栈里面东西是可读可写,所以我们可以改变里面的字符当把一个字符串常量赋值给一个字符数组的时候,那么它会把字符串常量中的没有字符都放在字符数组里
3)使用字符指针来保存字符串,它保存的是字符串常量地址,常量区是只读的,所以我们不可以修改字符串中的字符
10.二维字符串数组:
一维字符数组
char ch[10]={'a','b'};
char ch1[]="abc";
二维字符数组
char ch2[3][10]={{'a','b'},{'b'},{'c'}};
用二维数组来保存多个字符串
//用二维的字符数组可以存储多个字符串
//第一维存的是每个字符串的首地址
//每个字符串的长度,不能超过第二维长度
charch3[3][5]={"abc","def","kkkk"}
a b c \0 \0
d e f \0 \0
k k k k \0
ch[1][3] = 'Z';
11. #include <stdio.h>
int main(int argc, const char *argv[]) {
//char 类型的指针数组
char*name[3]={"abcdasfadsfasdfasdfasdf","def","kkk"}
for (int i=0; i<3; i++) {
//name[i]
printf("%s\n",*(name+i));
}
//字符串指针和字符数组的区别
//字符串指针:
char *ss ="abc";
//指向可以改变
//ss是一个指针变量
ss ="helloWorld!";
//字符数组:
chars1[]="abc";
//s1是数组名,是一个常量,不能被复制
//s1 ="helloworld!";
return 0;
}