c语言自学教程——初遇大魔王指针(前篇)

122 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

目前在不断更新《c语言自学教程》
未来会讲到《数据结构算法》,《C++语言》,《Linux系统编程》,《Linux网络编程》,《MySQL数据库》等。
期待系统学习编程的小伙伴可以关注我,不错过!

1. 指针是什么

指针是什么?指针的理解有两个要点

  1. 指针是内存中一个最小单元的编号,也就是地址
  2. 平时口语中说的指针,通常指的是指针变量,也就是存放内存地址的变量

总结:指针就是地址,口语中的指针通常指的是指针变量 在这里插入图片描述
这些编号又是如何产生的? 经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。

对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0) 那么32根地址线产生的地址就会是:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 ... 11111111 11111111 11111111 11111111

会产生2的32次方个地址 每个地址标识一个字节,那我们就可以给 (2^32Byte == 2^32/1024KB == 2^32 /1024/1024MB==2^32/1024/1024/1024GB == 4GB) 4G的空闲进行编址。 同理可得:64位的机器可以提供8G的空闲进行编址

我们用&(取地址操作符)取出一个变量的起始地址,可以存放在一个变量中,这个变量就叫做指针变量(指针)

#include <stdio.h>
int main()
{
	int a = 10;//在内存中开辟一块空间
	int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
	//a变量占用4个字节的空间,这里是将a的4个字节中第一个字节的地址存放在p变量中,p就是一个指针变量。
	return 0;
}

总结: 指针是用来存放地址的,地址是唯一标示一块地址空间的。 指针的大小在32位平台是4个字节,在64位平台是8个字节

2. 指针和指针类型

这里我们在讨论一下:指针的类型 我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢? 准确的说:有的。 当有这样的代码:

    int num = 10;
    p = &num;

要将&num(num的地址)保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢? 我们给指针变量相应的类型。

	char *pc = NULL;
	int *pi = NULL;
	short *ps = NULL;
	long *pl = NULL;
	float *pf = NULL;
	double *pd = NULL;

这里可以看到,指针的定义方式是: type + * 。 其实: char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放short类型变量的地址。 int* 类型的指针是为了存放 int 类型变量的地址。

既然32位机器下每个指针大小都为4(64位机器下每个指针大小都为8) 那指针类型的意义是什么?

2.1 指针+-整数

#include <stdio.h>
int main()
{
	int n = 10;
	char *pc = (char*)&n;
	int *pi = &n;
	printf("%p\n", &n);//0x0014F9F8
	
	printf("%p\n", pc);//0x0014F9F8
	printf("%p\n", pc+1);//0x0014F9F9
	
	printf("%p\n", pi);//0x0014F9F8
	printf("%p\n", pi+1);//0x0014F9FC
	return 0;
}

总结:指针的类型决定了指针向前或者向后走一步有多大(距离)

2.2 指针的解引用

#include <stdio.h>
int main()
{
	int n = 0x11223344;
	char *pc = (char *)&n;
	int *pi = &n;
	*pc = 0; //重点在调试的过程中观察内存的变化。//0x11223300
	*pi = 0; //重点在调试的过程中观察内存的变化。//0x00000000
	return 0;
}

总结: 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。