关于学数据结构前需要掌握的C知识总结(指针1)

前言:

因为数据结构这本书很多人学起来会十分的困难,数据结构也得确实很难的,因为数据结构需要很多C的知识铺垫才能够学习,其中指针和结构体在用C描述的数据结构中的作用是不可替代的,如果你不明白这些东西,在数据结构这个到处都是伪代码的书中几乎是难以前行的,所以就想总结一些学数据结构之前大家需要掌握的知识。

指针

指针: 通过地址能找到所需的变量单元,可以说地址指向该变量单元,我们将地址形象化的称之为指针。(一个变量的地址称为该变量的指针)
1.指针变量
如果有一个变量专门用来存放另一变量的地址(即指针),则称它为指针变量。
例:

int a = 19;
int* point_1;
point_1 = &a;
printf("%d,%d,%d,%d\n", a, &a,point_1,*point_1);

在这里插入图片描述
在这个简单的程序中,能够发现这四个变量的结果,a=point_1 ,&a=point_1, 这是因为变量a的地址赋给了指针变量point_1,所以如果以%d 形式输出指针变量时,它的值其实就是变量a的地址,当point_1被指向时,就是point_1 ,因为指针变量就是a的地址,所以*point_1的值其实就是a所代表的值。简单的理解,在这里指针变量就是地址,指针就是值。

那么如果指针变量没有指向任何变量,他的值又会是怎么样的呐?
如果通过程序来运行的话,你会发现行不通,编程软件会提示你变量未初始化,但是实际上,如果你没有对一个变量进行初始化的话,它的值就是个未知的,随机的。

2. 如何定义指针变量
类型名+ * 指针变量名
如 int * point_1
(这里需要注意的是,类型名是int *而不是int,int *表示的是指向整型变量的指针,int 表示定义一个整型变量,这是不一样的,而point_1才是指针类型名,对于其他的如字符型都同理即可)
3. 指针的初始化
你可以选择先定义一个指针变量然后将它赋值,也就是我们所说的将它指向某个变量,我们也可以在定义时直接将它赋值
如:int *point_1=&a;
也可以
int * point_1;
point_1=&a;
在这里我们把int等类型称之为基类型,当你定义的时候千万不要忘记。基类型的不一样,代表他们的内存中所代表的字节数不一样,如整形数据是4个字节,而字符型则是1个字节.当我们移动指针的时候,如果基类型是整型的话,一次就是移动了四个字节(如图所示),其余的同理;

int a = 19;
int* point_1;
point_1 = &a;
point_1++;
printf("%d,%d\n",  &a,point_1);

在这里插入图片描述

(这里需要注意的是千万不要写成 * point_1=&a; 这里是错误的,因为我们知道他们的类型都是不一样的,又怎么能赋值呐?)
4. 引用指针变量
对于指针变量point_1来说,我们引它有很多种形式
1.直接引用:
例如 pirntf("%d",point_1);
也可以在某些赋值式中引用,例如 point_1=&a;
2.间接引用
例如:
当写出一个带有函数体的函数时,指针指向了某个变量,而对于参数来说,无论是实参还是形参,所传递的其本质上传递的都是指针,也就是指针所指向的变量的地址,我们叫做传址;
5. 指针数组
指针变量既然可以指向变量,当然也可以指向一个数组,实际上数组中的每个元素都有其对应的地址,而变量名所代表的地址,也可以说数组中第一个元素所代表的地址,其实就是该数组的地址,我们所说的指针指向该数组,说的就是指针指向的是该数组中的第一个元素的地址;

int a[4] = { 1,2,3,4 };
int* p;
p = &a[0];
printf("%d\n", *p);
p = a;
printf("%d\n", *p);

在这里插入图片描述
注意:p=a;的作用是把a数组中的首元素的地址赋值给指针变量P,而不是把数组中的所有元素的地址全部赋值给p;
在定义变量的时候也可以直接写成int * p=a;
6. 引用指针元素时指针的运算
指针就是地址,对指针的运算实质上就是对地址的运算;
例如 当p指向a[0]时,p+1 就是表示a[1] (这里加减乘除,自加,自减都适用,而当两个指针之间进行运算时,只有同时指向同一个数组时,才有意义)。
注意:数组名是一个指针型常量,它的值在程序运行期间是固定不变的,所以a++是无法实现的。
7. 通过指针引用数组元素
(1)下标法
(2)指针法
下面通过一个程序来解释两种方法:

	int *p,i,a[10];
p = a;
for (i = 0; i < 10; i++)
	scanf_s("%d", p++);

for (i = 0; i < 10; i++, p++)
		printf("%d", *p);
	printf("\n");
for (p=a,i = 0; i < 10; i++, p++)
		printf("%d", *p);
	printf("\n");
for (i = 0; i < 10; i++)
		printf("%d", a[i]);
	printf("\n");
for (p = a, p<(a+10); p++)
	printf("%d,", *p);  

在这里插入图片描述
由图片可以看出输出的第二行输出了乱七八糟的东西,其实是输出了10个地址,因为当p进行自增时,由于是地址上的自增,当循环之后,p最后实质上是指向了数组的最后一个元素,所以如果不让p重新指向的话,P在自增,就无法预料它所指向的地址,因为它超过了数组有效的界限;
8.指针的运算
这里主要需要说明的就是 *p++, * (p++), * (++p), ++*p, *++p,++(*p)的一些区别与相同点,下面我们用一段代码来掩饰这几个结果。

	int *p,i,a[10];
p = a;
for (i = 0; i < 10; i++)
	scanf_s("%d", p++); for (p = a, i = 0; i < 10; i++)
	printf("%d,", *p);       			printf("\n");
	for (p = a, i = 0; i < 10; i++)
		printf("%d,", *p++);			printf("\n");
	for (p = a, i = 0; i < 10; i++)
		printf("%d,", *(p++));			printf("\n");
	for (p = a, i = 0; i < 10; i++)
		printf("%d,", *(++p));			printf("\n");
	for (p = a, i = 0; i <10; i++)
		printf("%d,", ++ * p);			printf("\n");
	for (p = a, i = 0; i < 10; i++)
		printf("%d,", *++p);			printf("\n");
	for (p = a, i = 0; i < 10; i++)
		printf("%d,", ++(*p));

在这里插入图片描述
以上的差不多就是指针经过不同运算后的结果,读者通过对照应该不难看出各个运算方法所造成的原因,在这里就不加以解释了。
对于指针来说 数组名作为函数参数等知识在数据结构中极为重要,这些知识点的整理将在下一篇文章中整理,不要问为什么,因为好晚了,要睡了,最后希望我的总结对你有所帮助。

猜你喜欢

转载自blog.csdn.net/weixin_47160672/article/details/108629971