前言
在C语言中,指针是一个非常重要的概念,那么今天就让我们来深度解剖一下指针吧!
目录
一、指针是什么
指针,是一个变量,是用来存放地址的,是地址唯一标识一块内存空间。

二、指针变量的使用
1.指针定义和指向
在C语言中,通常使用 解引用(*) 来定义指针。
int main(){
int a = 10;
int* p = NULL;//定义指针p
*p = &a;//p指向a的地址
return 0;
}
在这个代码中,用int类型定义了指针p,指针p指向的是a的地址。
在定义中,指针变量与其他变量一样,都可以由许多类型来定义,例如char, short, int, double等等。
2.指针的大小
在C语言中,指针的大小是固定的。X86环境下是4个字节,而在X64环境下是8个字节。
3.指针的初始化
指针初始化是非常重要的,因为如果不初始化,这个指针就会变成野指针。
int* p = NULL;
4.指针+-整数

指针+-整数表示当前指针跳转到下几个地址,例如:指针+1 --> 下一个地址 指针+2 --> 下两个地址

指针跳过几个字节取决于类型的定义,例如int类型 +1就是跳过4个字节,char类型就是跳过1个字节,以此类推。
5.指针之间的运算
相同类型的指针之间是可以进行加减运算的,运算的结果是两个指针之间的元素个数。
int main()
{
int a[] = { 1,2,3,4,5 };
int* p1 = a;
int* p2 = a+2;
printf("%d\n", *p2 - *p1);
return 0;
}

6.指针与数组
指针与数组有着密切的关系。先看数组:数组名表示的是数组首元素。(例外:1.在sizeof函数中,数组名单独存放,则表示整个数组,sizeof(数组名)则表示整个数组的大小。
2. 取地址数组名。e.g. int arr[10]; &arr,arr则表示整个数组。)
int main()
{
int arr[] = { 1,2,3,4,5,6 };
printf("首地址是:%p\n", &arr[0]);
printf("arr表示的是:%p", arr);
return 0;
}

接着是指针:既然数组名可以表示首元素地址,那么指针指向首元素地址就可以表示这一个数组。
int main()
{
int arr[] = { 1,2,3,4,5,6 };
int* p = arr;
printf("%d\n", *p);
return 0;
}

所以我们发现,其实数组也可以看成一个指针。
三、指针种类
1.字符指针
在指针类型中,有一种指针类型叫做字符型指针,例如:char* s
在字符指针中,可以放字符或者字符串,如果放字符串,那么指针指向首元素的地址,与字符数组类似,但是不完全与字符数组相同。
int main()
{
char* s1 = "abcde";
char* s2 = "abcde";
char s3[] = "abcde";
char s4[] = "abcde";
if (s1 == s2)
{
printf("s1 == s2\n");
}
else
{
printf("s1 != s2\n");
}
if (s3 == s4)
{
printf("s3 == s4\n");
}
else
{
printf("s3 != s4\n");
}
return 0;
}
例如这一个代码,分别定义字符指针和字符数组,都初始化相同的值。但结果是
这就表明了,字符指针并不需要另外开辟内存空间,而是都指向同一个内存,而数组则是需要另外开辟内存空间来存储这些字符,所以两个字符数组的地址并不相同。这就是字符指针和字符数组的差别。
2.指针数组
顾名思义,指针数组是存放指针的数组。
int main()
{
int* arr[10];//整形指针数组
char* arr1[20];//一级字符指针数组
return 0;
}
3.数组指针
数组指针是指针,是用来存放数组的指针。
int main()
{
int(*p)[10];
return 0;
}
因为数组指针是指针,而 [ ] 的优先级高于 * ,所以要加上括号把 * 括起来。
数组指针的使用
数组指针一般在二维数组传参中使用。
void print(int(*p)[5], int a, int b)
{
int i = 0;
int j = 0;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
printf("%d ", p[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
print(arr, 2, 5);
return 0;
}

前面提到,数组名和指针指向的是首元素的地址,所以在这里,数组指针也是指向第一个数组的地址。
二维数组其实可以理解成多个一维数组组成的数组。所以数组指针指向的首数组的地址。
4.函数指针
从名字上来看,函数指针应当也是一个指针,是一个指向函数的指针。
函数地址
首先要了解如何表示函数的地址:1.&函数名,用取地址符号取出函数的地址。
2.函数名
其实与数组名类似,函数名也是可以表示函数的地址的。
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("%p\n", &Add);
printf("%p\n", Add);
return 0;
}

函数指针的定义
在上面我们知道了,函数名可以表示函数的地址,那么我们也可以顺带写出函数指针是如何定义的。
int(*a)(int, int) = Add;
首先,函数指针是指针,与数组指针类似,也是用(*)。
接着是与调用函数的用法类似,(函数参数)。
函数指针的使用
与指针的使用一样,解引用该指针,返回类型与函数相同。
int Add(int x, int y)
{
return x + y;
}
int main()
{
int(*a)(int, int) = Add;
int b =(*a)(3, 5);
printf("%d", b);
return 0;
}

5.函数指针数组
函数指针数组,就是用来存放函数指针的数组。
函数指针数组的定义可以参照指针数组。
int(*p[10])();//括号中填函数参数
如果我们有许多个函数,参数一样,返回类型一样,只是函数内容不一样,那么就可以用函数指针数组来进行调用,使函数的调用清晰可见。
这里我们直接举例子来更好的理解函数指针数组。e.g.计算器
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
int main()
{
int input = 1;
int x = 0;
int y = 0;
while (input)
{
printf("-------------------------------\n");
printf("-------1.add 2.sub--------\n");
printf("-------3.mul 4.div--------\n");
printf("-------0.exit -------------\n");
printf("请输入:");
scanf("%d", &input);
int (*ret[])(int x, int y) = { 0,Add,Sub,Mul,Div };
if (input >= 1 && input <= 4)
{
printf("请输入需要计算了两个数:");
scanf("%d%d", &x, &y);
printf("%d\n", (*ret[input])( x, y));
}
else
{
printf("输入有误!");
}
}
return 0;
}

在这个程序中,加减乘除的函数返回类型和函数参数一样,所以可以用函数指针数组来进行函数的调用。
以上就是指针的所有内容了,希望对大家有所帮助吧!!!
本文详细介绍了C语言中的指针概念,包括指针的定义、使用方法(如定义、初始化、运算、数组关联),以及各种特定类型的指针如字符指针、指针数组、数组指针和函数指针的特性和应用。
4021

被折叠的 条评论
为什么被折叠?



