C语言内存中的地图,方向盘,初始指针详解(1)

简介: C语言内存中的地图,方向盘,初始指针详解(1)

各位少年,大家好,我是博主那一脸阳光,今天给大家分享C语言中的指针的基本概念,由于指针的类型比较多,所以我们采取多篇博客来解释。

前言

在探索C语言的广袤世界中,指针无疑是最具魔力与深邃的元素之一。它就像一把神秘的钥匙,解锁了数据在内存中的秘密花园;又如同一位技艺高超的向导,引领我们在复杂的数据迷宫中自由穿行。

想象一下,你置身于一个巨大的图书馆,每一本书都代表着一块内存空间,存储着特定的信息。而“指针”,便是一张写有书架编号和位置的地图,指向那些珍贵的知识宝藏。当你手握指针,就拥有了瞬间抵达任意书籍的能力,可以阅读、修改或移动这些信息。在这个类比中,改变指针所指向的位置,就好比更换了书架上的书籍;通过指针来操作内存中的数据,则类似于翻阅书本并记录新的篇章。

因此,在C语言的舞台上,掌握指针的艺术就是掌握了高效操控内存和数据的秘诀。这不仅能帮助我们更深入地理解程序运行机制,更能使代码变得更加简洁且强大。让我们一起揭开指针的神秘面纱,以全新的视角去解读这个编程世界中不可或缺的角色。

内存和地址

假设有⼀栋宿舍楼,把你放在楼⾥,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩,

如果想找到你,就得挨个房⼦去找,这样效率很低,但是我们如果根据楼层和楼层的房间的情况,给

每个房间编上号,如:

⼀楼:101,102,103…

⼆楼:201,202,203…

有了房间号,如果你的朋友得到房间号,就可以快速的找房间,找到你。

bit - ⽐特位
byte - 字节
KB
MB
GB
TB
PB

我们知道计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数

据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何⾼ 效的管理呢?

其实也是把内存划分为⼀个个的内存单元,每个内存单元的⼤⼩取1个字节。 计算机中常⻅的单位(补充): ⼀个⽐特位可以存储⼀个2进制的位1或者0

⽣活中我们把⻔牌号也叫地址,在计算机中我们 把内存单元的编号也称为地址。C语⾔中给地址起 了新的名字叫:指针

所以我们可以理解为:

内存单元的编号 == 地址 == 指针

CPU访问内存中的某个字节空间,必须知道这个 字节空间在内存的什么位置,⽽因为内存中字节 很多,所以需要给内存进⾏编址(就如同宿舍很

多,需要给宿舍编号⼀样)。 计算机中的编址,并不是把每个字节的地址记录 下来,⽽是通过硬件设计完成的。 钢琴、吉他

上⾯没有写上“都瑞咪发嗦啦”这样 的信息,但演奏者照样能够准确找到每⼀个琴弦 的每⼀个位置,这是为何?因为制造商已经在乐

器硬件层⾯上设计好了,并且所有的演奏者都知 道。本质是⼀种约定出来的共识! 硬件编址也是如此。 ⾸先,必须理解,计算机内是有很多的硬件单

元,⽽硬件单元是要互相协同⼯作的。所谓的协 同,⾄少相互之间要能够进⾏数据传递。 但是硬件与硬件之间是互相独⽴的,那么如何通

信呢?答案很简单,⽤"线"连起来。 ⽽CPU和内存之间也是有⼤量的数据交互的,所 以,两者必须也⽤线连起来。

不过,我们今天关⼼⼀组线,叫做地址总线。 我们可以简单理解,32位机器有32根地址总线, 每根线只有两态,表⽰0,1【电脉冲有⽆】,那么

⼀根线,就能表⽰2种含义,2根线就能表⽰4种含 义,依次类推。32根地址线,就能表⽰2^32种含 义,每⼀种含义都代表⼀个地址。

地址信息被下达给内存,在内存上,就可以找到 该地址对应的数据,将数据在通过数据总线传⼊ CPU内寄存器。

总结

内存被划分为一个个的单元,一个内存单元的大小就是一个字节。
每个内存单元都给一个编号,这个编号就是地址,C语言中把地址又称为:指针
编号==地址==指针

指针变量和地址

取地址操作符(&)

理解了内存和地址的关系,我们再回到C语言,在C语言中创建变量其实就是向内存申请空间,比如:

#include <stdio.h>
int main()
{
 int a = 10;//向内存中申请四个字节
 return 0;
}

如何获得a的地址?

很显然用取地址操作符就可以了。

#include <stdio.h>
int main()
{
 int a = 10;
 &a;
 return 0;
}

这样我们就取到了a的地址,但是a的地址是什么呢?那不是我们得打印出来看看喽,看下面例子。

#include <stdio.h>
int main()
{
 int a = 10;
printf("%p\n",&a);//%p打印地址操作符
 return 0;
}

输入的结果是16进制的输出方式,一个16进制位就是4个二进制。把上面每个代码转换为二进制以后,就是在计算机内存储的地址(计算机存储的是二进制,打印的是16进制地址)。

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

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

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

```c
#include <stdio.h>
int main()
{
 int a = 10;
 int* pa = &a;//取出a的地址并存储到指针变量pa中
 
 return 0;
 }
```指针变量也是⼀种变量,这种变量就是⽤来存放地址的,存放在指针变量中的值都会理解为地址

我们看到pa的类型是 int* ,我们该如何理解指针的类型呢?

int a = 10;

int * pa = &a;

这⾥pa左边写的是 int* * 是在说明pa是指针变量,⽽前⾯的 int 是在说明pa指向的是整型(int)

类型的对象。

例子

那如果有⼀个char类型的变量ch,ch的地址,要放在什么类型的指针变量中呢?

char ch = 'w';
pc = &ch;//pc 的类型怎么写呢?

解引⽤操作符

我们将地址保存起来,未来是要使⽤的,那怎么使⽤呢?

在现实⽣活中,我们使⽤地址要找到⼀个房间,在房间⾥可以拿去或者存放物品。

C语⾔中其实也是⼀样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)

指向的对象,这⾥必须学习⼀个操作符叫解引⽤操作符(*)。

#include <stdio.h>
int main()
{
 int a = 100;
 int* pa = &a;
 *pa = 0;
 return 0;
}

上⾯代码中第7⾏就使⽤了解引⽤操作符, *pa 的意思就是通过pa中存放的地址,找到指向的空间,

pa其实就是a变量了;所以pa = 0,这个操作符是把a改成了0.

有同学肯定在想,这⾥如果⽬的就是把a改成0的话,写成 a = 0; 不就完了,为啥⾮要使⽤指针呢?

其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径,写代码就会更加灵活,

后期慢慢就能理解了。

指针变量的⼤⼩

前⾯的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后

是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4

个字节才能存储。

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

同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要

8个字节的空间,指针变的⼤⼩就是8个字节

#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;
}
总结

在C语言的奇幻旅程中,掌握指针运用的艺术就好比掌握了驾驭编程世界的魔法。它使我们能够以更直接、更灵活的方式触及程序运行的核心,赋予代码生命与活力。指针,这一强大的工具,不仅提升了我们对计算机底层运作机制的认知深度,也极大地拓宽了问题解决的可能性空间。

犹如那神秘的地图指引着我们在信息的海洋里游刃有余,善用指针,就如同手持一把解开内存迷局的万能钥匙,于无形之中驾驭数据流转的脉络。因此,在这场探索之旅的终点,每一位深入钻研C语言的勇者都将领略到指针所带来的无穷魅力和无尽潜力。让我们携手揭开更多未知的秘密,共同驾驭这把开启高效编程之门的“金钥匙”,在C语言的世界里书写属于我们的精彩篇章。

相关文章
|
22天前
|
存储 C语言
指针和动态内存分配
指针和动态内存分配
77 0
|
2天前
|
存储 C语言
【C语言基础】一篇文章搞懂指针的基本使用
本文介绍了指针的概念及其在编程中的应用。指针本质上是内存地址,通过指针变量存储并间接访问内存中的值。定义指针变量的基本格式为 `基类型 *指针变量名`。取地址操作符`&`用于获取变量地址,取值操作符`*`用于获取地址对应的数据。指针的应用场景包括传递变量地址以实现在函数间修改值,以及通过对指针进行偏移来访问数组元素等。此外,还介绍了如何使用`malloc`动态申请堆内存,并需手动释放。
|
5天前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
10天前
|
存储 大数据 C语言
C语言 内存管理
本文详细介绍了内存管理和相关操作函数。首先讲解了进程与程序的区别及进程空间的概念,接着深入探讨了栈内存和堆内存的特点、大小及其管理方法。在堆内存部分,具体分析了 `malloc()`、`calloc()`、`realloc()` 和 `free()` 等函数的功能和用法。最后介绍了 `memcpy`、`memmove`、`memcmp`、`memchr` 和 `memset` 等内存操作函数,并提供了示例代码。通过这些内容,读者可以全面了解内存管理的基本原理和实践技巧。
|
10天前
|
缓存 Linux C语言
C语言 多进程编程(六)共享内存
本文介绍了Linux系统下的多进程通信机制——共享内存的使用方法。首先详细讲解了如何通过`shmget()`函数创建共享内存,并提供了示例代码。接着介绍了如何利用`shmctl()`函数删除共享内存。随后,文章解释了共享内存映射的概念及其实现方法,包括使用`shmat()`函数进行映射以及使用`shmdt()`函数解除映射,并给出了相应的示例代码。最后,展示了如何在共享内存中读写数据的具体操作流程。
|
10天前
|
存储 安全 C语言
C语言 二级指针应用场景
本文介绍了二级指针在 C 语言中的应用,
|
26天前
|
存储 编译器 C语言
【C语言篇】深入理解指针2
代码 const char* pstr = "hello world."; 特别容易让初学者以为是把字符串 hello world.放 到字符指针 pstr ⾥了,但是本质是把字符串 hello world. 首字符的地址放到了pstr中。
|
26天前
|
存储 程序员 编译器
【C语言篇】深入理解指针1
assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为“断⾔”。
|
22天前
|
存储 NoSQL 程序员
C语言中的内存布局
C语言中的内存布局
24 0
|
26天前
|
C语言
【C语言】指针速览
【C语言】指针速览
15 0