本文已参与「新人创作礼」活动,一起开启掘金创作之路。
C语言指针
(一)各种指针的定义
1.一个整型数 : int a;
2.一个指向整型数的指针: int *a;
3.一个指向指针的指针,它指向的指针指向一个整型数: int **a;
4.一个有10个整型数的数组:int a[10];
5.一个有10个指针的数组,每个指针指向一个整型数:int *a[10];
6.一个指向有10个整形数的数组的指针:int (*a)[10];
7.一个指向指针的指针,被指向的指针指向一个有10个整型数的数组:int (**a)[10];
8.一个指向数组的指针,该数组有10个整形指针:int *( *a)[10];
9.一个指向函数的指针,该函数有一个整形参数并返回一个整形数:int (*a)(int);
10.一个有10个指针的数组,每个指针指向一个函数,该函数有一个整形参数并返回一个整形数:int (*a[10])(int );
11.一个函数的指针,指向的函数的类型是有两个整形参数并且返回一个函数指针的函数,返回的函数指针指向有一个整形参数且返回整形数的函数:int (* ( *a)(int,int))(int);
(二)各种指针的介绍
1.int a;
a 是一个变量,指向内存的一个空间地址,通过&a得到该地址空间,通过a可以取到该地址空间中的值。
2.int *a;
定义了一个指向整形数的指针a,a是一个返回值是整型数的指针。有一个变量int x;a=&x;a便指向了x的地址空间,通过*a可以取出地址空间中的数据,值和x是一致的。
通过代码来深入理解一下
#include<stdio.h>
int main()
{
int a = 10;
int *p = &a;
printf("变量名访问a:%d\n",a);
printf("a的地址是:%p\n",&a);
printf("地址访问a:%d\n",*(&a));
printf("指针访问a的地址是%p\n",p);
printf("指针变量访问a:%d\n",*p);
return 0;
}
运行结果如下:
3.int **a;
定义了一个二级指针a,返回值是整型的指针,有变量int y;int *b=&y; int **a=&b;
b指向y的地址,a指向b的地址,b中存放的是y的地址,a中存放的是b的地址,通过*a可以得到b的地址,由于是二级指针,**a便取到了y的值。
代码示例
#include<stdio.h>
int main()
{
int a = 10;
int *p = &a;
int **pp = &p;
printf("通过变量名访问a:%d\n",a);
printf("通过地址访问a:%d\n",*(&a));
printf("通过一级指针p访问a:%d\n",*p);
printf("二级指针pp访问a:%d\n",*(*pp));
printf("a的地址为:%p\n",&a);
printf("一级指针:a的地址%p\n",p);
printf("p的地址为:%p\n",&p);
printf("二级指针pp访问打印p的地址:%p\n",pp);
return 0;
}
~
运行结果
4.int a[10];
定义了一个整型数的数组,大小为10,有10个元素。可以通过数组名加下角标进行访问数组的数据,下角标为0-9,其他的为数组越界。
代码示例
#include<stdio.h>
int main()
{
int a[10] ={1,2,3,4,5,6,7,8,9,10};
int size = sizeof(a)/sizeof(a[0]);
for(int i=0;i<size;i++){
printf("%d ",a[i]);
}
putchar('\n');
return 0;
}
运行结果
5.int *a[3];
定义了一个指针数组,数组中的每一个元素都是指针,指向内存的某一个空间地址。
如:有三个变量int x,y,z;int *a[3]={&x,&y,&z};
分别将三个指针指向x,y,z的地址空间。
代码示例:
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 40;
int *arr[3] = {&a,&b,&c};
for(int i=0;i<3;i++){
printf("%d ",*arr[i]);
}
putchar('\n');
return 0;
}
运行结果
6.int (*a)[3];
数组指针,定义一个指针,指向一个数组。
数组指针才是真正等同于二维数组名。
代码示例
#include<stdio.h>
int main()
{
int arr[3][4] = {{11,22,33,44},{12,13,14,15},{13,45,67,88}};
int (*a)[4];
a = arr;
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
printf("%d ",*(*(a+i)+j));
}
putchar('\n');
}
putchar('\n');
return 0;
}
运行结果
void (*p)();
返回值为void 的无参数的函数指针
示例
#include<stdio.h>
void Print()
{
puts("程序启动,欢迎使用!");
}
int main()
{
void (*p)();
p = Print;
(*p)();
return 0;
}
运行结果:
int (*p2)(int );
返回值为int类型,形式参数为一个int类型的函数指针
代码
#include<stdio.h>
void Print()
{
puts("程序启动,欢迎使用!");
}
int GetData(int data)
{
printf("%d\n",data);
}
int main()
{
void (*p)();
int (*p2)(int);
p2 = GetData;
p = Print;
(*p)();
(*p2)(10);
return 0;
}
运行结果
7.int(**a)[2];
相当于一个二级指针,它存放的是一个指针的地址,这个指针指向有2个元素的数组。
代码示例
#include<stdio.h>
int main()
{
int arr[2][2]={{1,2},{3,4}};
int (*p2)[2] = arr;
//int **a = &p2;
int (**a)[2] = &p2;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d ",arr[i][j]);
}
printf("\n");
}
printf("\n");
//printf("%d\n",arr[0][0]);
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d ",*(*(p2+i)+j));
}
printf("\n");
}
printf("\n");
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d ",*(*(*a+i)+j));
}
printf("\n");
}
putchar('\n');
return 0;
}
运行结果
8.int*( *a)[2];
相当于一个二级指针,存放是一个数组的地址,数组中有2个整型数的指针。
9.int *a(int);
这是一个函数指针,指向某个函数的地址空间。该函数有以一个整形参数。
10.int (*a[3])(int );
这是一个数组,数组中存放的是3个指针,每一个指针指向一个函数。也就是函数指针的数组。
代码
#include<stdio.h>int GetMax(int a,int b){ return a>b?a:b;}int GetMin(int a,int b){ return a<b?a:b;}int GetSum(int a,int b){ return a+b;}int main(){ int a = 10; int b = 20; int ret; int (*p[3])(int,int) = {GetMax,GetMin,GetSum}; for(int i=0;i<3;i++){ ret = (*p[i])(a,b); printf("ret = %d\n",ret); } return 0;}
运行结果
11.int (* ( *a)(int,int))(int);
这是一个函数指针,其指向的函数是带有两个形参的函数,并且返回值为函数指针,返回的函数指针是带一个形参,并且返回值为整型,也就是返回的函数指针指向带一个形参并且返回值为int 的函数。