C语言指针

本文详细介绍了C语言中的指针概念,包括指针的定义、使用方法(如定义、初始化、运算、数组关联),以及各种特定类型的指针如字符指针、指针数组、数组指针和函数指针的特性和应用。

前言

在C语言中,指针是一个非常重要的概念,那么今天就让我们来深度解剖一下指针吧!

目录

前言

一、指针是什么

二、指针变量的使用

1.指针定义和指向

2.指针的大小

3.指针的初始化

4.指针+-整数

5.指针之间的运算

6.指针与数组

三、指针种类

1.字符指针

2.指针数组

3.数组指针

数组指针的使用

4.函数指针

函数地址

函数指针的定义

函数指针的使用

5.函数指针数组


一、指针是什么

指针,是一个变量,是用来存放地址的,是地址唯一标识一块内存空间。

二、指针变量的使用

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;
}

在这个程序中,加减乘除的函数返回类型和函数参数一样,所以可以用函数指针数组来进行函数的调用。

以上就是指针的所有内容了,希望对大家有所帮助吧!!!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值