C语言指针总结

101 阅读4分钟
#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;

结构体指针

结构体二级指针

总结

b0e73ac96005189aca16f88997a8952.png

注意符号的优先级,()的优先级要大于*。

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表示一个函数指针,这个函数有两个整型参数并且返回值是一个指针

指针类型比较复杂的时候,可以根据运算符号优先级和补全原则来逐层确定指针类型