【C语言指针一】从入门到通透:核心知识点全梳理(内存、变量、运算、const修饰)

🎬 个人主页秦苒&
专栏传送门 :《C语言

🍀指尖燃热血,代码铸锋芒;以信仰破局,向顶峰生长


🎬秦苒&的简介:


前言:今天这篇文章,我会把指针的核心模块(对应目录里的内存基础、指针变量、类型意义、const修饰、指针运算)拆解开,从"是什么""为什么""怎么用"三个维度做系统化梳理:小到指针变量的大小,大到指针减指针的本质,尽量用直白的逻辑+案例帮你把这些知识点串成一张清晰的网。

不管你是刚接触指针的新手,还是想补全知识漏洞的进阶学习者,跟着这篇梳理走,应该能让"指针"从"抽象概念"变成你代码里顺手的工具~

ps:由于篇幅有限,关于指针的学习我会分成多篇文章介绍。


文章目录


提示:以下是本篇文章正文内容,下面案例可供参考

一、内存和地址

1.1内存

计算机中的内存地址,本质就是内存空间的"门牌号" ------内存是由无数个"存储单元"(类似小抽屉)组成的,每个单元能存1字节(8位)数据

内存地址就是给每个"小抽屉"分配的唯一编号,让CPU能快速找到并读写对应的数据。

像这样:

核心类比(一看就懂):把内存想象成一栋巨大的"数据公寓",每一间房就是一个存储单元(存1字节数据),内存地址就是每间房的门牌号(比如1001、1002...)。CPU要读取/写入数据时,只要知道对应的"门牌号"(地址),就能直接找到目标房间,不用挨个翻找,极大提升效率。

在计算机中,也是如此!

在计算机中,我们把内存单元的编号称为内存地址,而C语言中的地址叫指针。

因此我们理解为:
内存单元的编号== 地址 ==指针

这里我补充一下计算机中常见单元如下:
1Byte=8bit
1KB = 1024Byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB

1.2编址

什么是编址?

"编址"(内存编址),就是给计算机内存的每一个存储单元,分配一个唯一的编号(也就是咱们刚说的内存地址)的过程------本质是"给内存的'小抽屉'编门牌号",让CPU能通过编号精准找到对应单元,是内存和CPU通信的基础。

为什么要编址?

解决"CPU找不到数据"的问题。如果不编址,内存里的几十亿个存储单元就是"乱堆的抽屉",CPU要找一个数据得挨个翻,速度慢到无法使用;编址后,每个单元有唯一地址,CPU直接"按号找房",效率拉满。

怎么样编址?

编址是"分配地址"的过程,分配完之后,每个变量(比如 int a=10 )在内存中占用的单元,就有了自己的地址( &a );而指针( int *p ),就是用来存这个"编好的地址"的变量------相当于"你先给房间编好门牌号(编址),再把门牌号写在纸条上(指针p),CPU拿着纸条就能找到房间(变量a)

我们结合图片理解一下:

而上图中的CPU和内存属于硬件,硬件和硬件之间是相互独立的。为了让硬件间相互通信,我们用"线"将他们连起来。

今天我们先了解"地址总线"。

我们可以简单理解,32位机器有32根地址总线,每根线只有两态,表示0,1【电脉冲有无】,那么⼀根线,就能表示2种含义,2根线就能表示4种含义,依次类推。32根地址线,就能表示2^32种含义,每⼀种含义都代表⼀个地址。地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传入CPU内寄存器。

二、指针变量和地址

2.1取地址操作符(&)

题外话:话说我名字(秦苒&)就有这个符号,这可不是随便取的名字,等指针这一板块知识点全部整理完,我给大家解释一下吧!

进入正题!!

在C语言中创建变量就是在向内存申请空间。比如说:

上述的代码就是创建了整型变量a,内存中申请4个字节,⽤于存放整数10,其中每个字节都有地址,上图中4个字节的地址分别是:

0x006FFD70

0x006FFD71

0x006FFD72

0x006FFD73

怎么样得到a的地址呢?

我们就需要引入&---取地址操作符

总结:
指针---地址
指针变量---存放地址的变量

c 复制代码
#include<stdio.h>
int main()
{
  int a = 0;
  &a;//取出a的地址
  printf("%d\n",&a);
  return 0;
}

&a取出的是a所占4个字节中地址较小的字节的地址

则 打印结果为:006FFD70

虽然整型变量占用4个字节,我们只要知道了第⼀个字节地址,访问到4个字节的数据也是可行的。

2.2指针变量和解引用操作符(*)

我们通过取地址操作符(&)拿到的地址是⼀个数值,比如:0x006FFD70,这个数值有时候也是需要

存储起来,方便后期再使用的,那我们把这样的地址值存放在哪里呢?答案是:指针变量中。

c 复制代码
#include <stdio.h>
 int main()
 {
 int a = 10;
 int * pa = &a;//取出a的地址并存储到指针变量pa中
 return 0;
 }

指针变量也是⼀种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。

上述代码中:

int*是pa的类型,*是在说明pa是指针变量,而前面的int 是在说明pa指向的是整型(int)类型的对象

  • 如何使用地址?
    我们只要拿到了地址(指针),就可以通过地址(指针)找到地址针指向的对象,这里必须学习⼀个操作符叫解引用操作符(*)。
  • *pa 的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量了;所以 *pa=0,这个操作符是把a改成了0.

2.3指针变量的大小

如果指针变量是用来存放地址的,那么指针变量的大小就得是4个字节的空间才可以。

即64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要8个字节的空间,指针变量的大小就是8个字节。

c 复制代码
#include <stdio.h>
//指针变量的⼤⼩取决于地址的⼤⼩ 
//32位平台下地址是32个bit位(即4个字节) 
//64位平台下地址是64个bit位(即8个字节) 
int main()
{
printf("%zd\n", sizeof(char *));
printf("%zd\n", sizeof(short *));
printf("%zd\n", sizeof(int *));
printf("%zd\n", sizeof(double *));
return 0;
}

输出结果为:

于是我们得到以下结论
·32位平台下地址是32个bit位,指针变量大小是4个字节
·64位平台下地址是64个bit位,指针变量大小是8个字节
·注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的

三、 指针变量类型的意义

指针变量的大小和类型无关,只要是指针变量,在同⼀个平台下,大小都是⼀样的。为什么还要有各种各样的指针类型呢?其实指针类型是有特殊意义的!大家接着看,听我为大家分析!

3.1指针的解引用

通过观察,我们不难发现:char* 的指针解引用就只能访问一个字节,而int* 的指针的解引用就能访问四个字节

即为:指针的类型决定了,对指针解引用的时候有多大的权限(⼀次能操作几个字节)

3.2指针±整数

大家注意观察指针的变化:

c 复制代码
#include <stdio.h>
int main()
{
  int n = 10;
  char *pc = (char*)&n;
  int *pi = &n;
	printf("&n=%p\n", &n);
	printf("pc=%p\n", pc);
	printf("pc+1=%p\n", pc + 1);
	printf("pi=%p\n", pi);
	printf("pi+1=%p\n", pi + 1);
return  0;
}

运行结果如下:

通过观察我们发现:

·指针变量的大小和类型无关

·char* 类型的指针变量+1跳过1个字节,int* 类型的指针变量+1跳过了4个字节。这就是指针变量的类型差异带来的变化。指针+1,其实跳过1个指针指向的元素。指针可以+1,那也可以-1

结论:
指针变量的类型决定指针前进或后退的距离(可以一次跳过几个字节)

3.3 void* 指针

void* 可以理解为⽆具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接受任意类型地址。

c 复制代码
#include<stdio.h>
int main()
{
  int a = 10;
  int* pa = &a;
  char* pc = &a;
  return 0;
}

因为我们将int型的变量的地址赋给了char*型的指针变量,因此编译器出现报错:

在这时,就体现了void* 类型的指针的作用。只要我们把int* 改为void*,程序便可以正常运行啦!

但是需要注意的是无法直接进行指针运算

但是如果我们给出啦指针的类型,程序正常运行结果如下:

总结:⼀般void* 类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。使得⼀个函数来处理多种类型的数据,在后面的博客我会详细解说。


四、const 修饰指针

4.1 const修饰变量

去掉第五行(n=20;)的运行结果:

4.2 const修饰指针变量

const修饰指针变量,可以放在 * 的左边,也可以放在 * 的右边,意义是不⼀样的。

• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。

但是指针变量本⾝的内容可变。

• const如果放在 * 的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变

五、指针的运算

指针的基本运算有三种
• 指针±整数
• 指针-指针
• 指针的关系运算

接下来听我逐一介绍:

5.1 指针±整数

前提:同类型且指向同一个连续内存块(比如同一数组),否则结果是未定义的
只有 char* 的指针相减(因为 char 占1字节)结果才等于"字节数"。

5.2指针-指针

5.3指针的关系运算

总结

C语言指针的核心,其实是"通过地址操控内存"------从内存编址的底层逻辑,到指针变量的"存地址、解引用",再到类型、const、运算这些规则,本质都是围绕"如何安全、高效地操作内存"展开的。

如果你看完这篇还觉得晕,不妨记住这3个"锚点":

· 指针变量存的是地址, & 是"拿地址", * 是"用地址里的内容";

·指针类型决定操作范围: char* 动1字节、 int* 动4字节,运算结果是"元素个数"而非字节数;

· 规则是"保护盾":const限定操作权限,指针运算只在同一块连续内存里合法,踩线就会出bug。

把这些锚点和实际代码结合(比如用指针遍历数组、传址修改变量),指针很快就能从"抽象概念"变成你写代码的"顺手工具"。

结尾

勇敢的寻宝者啊,这次旅途你挖掘到多少宝藏呢,苒苒很期待下次与您相遇!

结语:希望对寻找C语言相关内容的寻宝者有所帮助,不要忘记给博主"一键三连"哦!你的每一次鼓励都为我提供 了前行的动力!

小喵很期待与你再次寻宝奥 ᰔᩚ/•᷅•᷄\୭

相关推荐
星释2 小时前
Rust 练习册 111:构建锦标赛积分榜系统
开发语言·后端·rust
蓑衣夜行2 小时前
QtWebEngine 自动重启方案
开发语言·c++·qt·web·qwebengine
Source.Liu2 小时前
【LibreCAD】点实体源码解析
c++·qt·cad
lsx2024062 小时前
XQuery 实例详解
开发语言
hefaxiang2 小时前
猜数字小游戏--用分支和循环实现
c语言·开发语言
小清兔2 小时前
一个unity中URP的环境下旋转天空盒的脚本(RotationSky)
开发语言·数据库·学习·程序人生·unity·c#·游戏引擎
San30.2 小时前
从原型链到“圣杯模式”:JavaScript 继承方案的演进与终极解法
开发语言·javascript·原型模式
乌托邦2号3 小时前
Qt5之中文字符串转换
开发语言·qt
煤球王子3 小时前
学而时习之:C++中的标准模板库7
c++