#include <stdio.h>
int main(){
int data=100;
int *p=&data;
printf("data的地址是%p\n",&data);
printf("p保存data的地址%p,内容是%d\n",p,*p);
printf("p的地址是%p\n",&p);
int *pp=&p;
printf("pp保存p的地址:%p\n",pp);
//可以发现,格式控制符与变量格式有关,如果内容是数据,则为d;如果内容是地址,则为p
printf("*pp是%p\n",*pp);
}
data的地址是000000000061FE14
p保存data的地址000000000061FE14,内容是100
p的地址是000000000061FE08
pp保存p的地址:000000000061FE08
*pp是000000000061FE14
1.指针变量
int *p //定义一个指针
p是指针,存放变量的地址
*p所指变量的内容
&p是指针的地址
野指针
2.数组指针
数组指针是数组的指针
int arr[5]={1,2,3};
int (*a)[5]=&arr;
可以发现,数组名只有在函数中可以被视为指针,其他情况下要表示数组指针时,必须取地址
3.二维数组指针
二维数组名等价于一个数组指针
int scores[3][4];
int (*p)[4];
4.函数指针
int a;
int *p;
char c;
char *p;
int getData(int a, int b){
}
int *p(int a,int b);
p=getData;
void swap (int a, int b){
}
void *p(int a,int b);
p=swap;
5.指针偏移
6.指针数组
数组指针与指针数组
#include<stdio.h>
int main(){
int name=10; int name1=11; int name2=12;
int *m=&name; int *n=&name1;int *q=&name2;
int *a[3]={m,n,q};//数组名为a
int arr[3]={1,2,3};
int (*b)[3]=&arr;//指针名为b
//可以发现,数组名只有在函数中可以被视为指针,其他情况下要表示数组指针时,必须取地址
printf("%p\n",a);//000000000061FDC0
printf("%p\n",*a);//000000000061FDEC
printf("%p\n",b);//000000000061FDB4
printf("%p\n",*b);//000000000061FDB4
for(int i=0;i<3;i++){
printf("%d\n",*(*a+i));
}
/*10
6421940
0*/
for(int i=0;i<3;i++){
printf("%p\n",*(a+i));
}
/*000000000061FDEC
000000000061FDE8
000000000061FDE4*/
for(int i=0;i<3;i++){
printf("%d\n",*((*b)+i));
}
/*1
2
3*/
for(int i=0;i<3;i++){
printf("%p\n",*(b+i));
}
return 0;
}/*000000000061FDB4
000000000061FDC0
000000000061FDCC*/
7.指针函数
8.多级指针
对野指针进行访问时发生段错误
不可以简单地认为二级指针和二维数组直接进行联系
需要先设一个指针指向一维数组,然后再进行取地址
int scores[3][4];
int (*p)[4]=scores;
int **p2=&p;
**p3=100;
结构体指针
结构体二级指针
总结
注意符号的优先级,()的优先级要大于*。
int *a; 一个整型变量的指针
int **a; 一个二级指针,指向指针的地址,还可以引出多级指针
int *a[];一个指针数组,数组中存放的全是指针,每个指针指向一个整型数
int name=10;int name1=11;int name2=12;
int *m=&name; int *n=&name1;int *q=&name2;
int *a[3]={m,n,q};//数组名为a
int (*a)[]; 一个整型变量数组的指针,指针名为a
int arr[3]={1,2,3};
int (*a)[3]=&arr;
int (** a)[]; 根据运算符的优先级,()优先,因此先看括号内的结合** a。** a是一个二级指针,被指向的指针指向了一个数组,这个数组存放的是整型变量
int arr[3]={1,2,3};
int (**a)[3]=&arr;
int (*a)(int);函数指针,指针直接指向函数,通过指针调用函数
void print(){
puts("welcome!");
}
int main(){
void(*p)();//定义一个函数指针变量
p=print;//指针指向函数
print();//直接调用函数
(*p)();//通过指针调用函数
}
int (*a[10])(int);一个有10个指针的数组,每个数组指向了一个返回值为整型的函数,这个函数有一个整型参数
void print(){
puts("welcome!");
}
a[0]=print; //指针指向函数
(*a[0])();
int (*a[10])(int int);补全原则: int *a[10]。一个有10个指针的数组,每个数组指向了一个返回值为整型的函数 ,这个函数有两个整型参数 (数组指针指向的函数类型就是外面的这个函数类型)
int* (*a)(int);a是一个函数指针,指向的函数返回值是int *,是一个指针
int (*(a)(int int))(int int);根据符号优先级原则,第一个括号内为(a)(int int),补全原则: int(*a)(int int) 显然,a表示一个函数指针,这个函数有两个整型参数并且返回值是一个指针
指针类型比较复杂的时候,可以根据运算符号优先级和补全原则来逐层确定指针类型