室友收了个房租,搞懂了C语言的指针

简介: 室友收了个房租,搞懂了C语言的指针

☘前言☘

变量的指针、指针变量

指针数组、数组指针

指针函数、函数指针

每个被C语言劝退的伙伴们是否看到这些概念脑壳疼,那种支配感觉扑面而来0.0

这次我就用一个小故事帮大家打通一下指针相关的任督二脉0.0


🗡1.1 指针究竟是什么

先放上一张神图。大名鼎鼎的冯·诺伊曼体系结构。

374ee199c33012165442f784fe9000b.png

可以发现运算器能直接读取的程序是在存储器内的。那么运算器怎么拿到这个数据呢?

首先我们先明确,因为变量的读取都是从内存中的,所以一定会有一片空间在内存中。我们把它想象成有一栋公寓有一堆房间,我们想要找到我们的房间是不是得有个房间号?

e14d68c6b2c0d99e0f558ebc6005313.png

然后有没有发现102 103 104 105这四个房间我没画隔断,因为很多地方是按照门来编号的,但是一个大房间可能对应多个门呀。


 上面的门的编号方式就是编制方式(可以一个门一个号,也可以两个门一个号),地址就               每个门的房号,然后数据其实就是门内的内容。

 我们根据房号找到家,计算机就是根据地址找到数据。

指针其实就是地址。也就是上面的房号。

我们假如忘了门号就看看外面门上的标识牌对吧?计算机内如果变量想要直到自己的地址也是需要看看自己的房号,怎么去看呢?用&,因为是变量自己看所以就是&x就拿到地址啦0.0

举个例子:


#include<cstdio>
int main(){
  int a = 0;
  printf("%d %d\n", &a,a);
  return 0;
}


输出结果可能是:2686748 1

其中地址是一个unsigned类型的整数(64位是unsigned longlong),至于为啥是无符号的,你见过谁家房号是负数么0.0


🛡1.2指针变量

指针变量用来存放地址,然后可以看下图,就是指针变量,比较厉害,手里有把钥匙,并且这个钥匙可以开对应的门。

bfce61878c684743d0dac6543088e03.png

然后由于这是一把钥匙,所以在声明它的时候需要在它前面加个*,表示它是一把钥匙。也就是int *p;,一般来说都是把*放在变量前面。

同时*也表示拿钥匙开门,*p就表示拿到对应的数据,所以图上的就是104号房间对应的元素。

刚才知道&是取地址,就是看看房间号,那么p = &a就可以把p这把钥匙变成a所对应的地址。此时再去*p就是a的值。

看下面的程序:


#include<cstdio>
int main(){
  int a;
  int *p = &a;
  *p = 233;
  printf("%d %d", *p, a);
  return 0;
}


输出结果是233 233,因为开房间的优先级很高,在赋值的时候是先打开门,再把数据写入,所以就把值写入到了a之中。最后输出就是两次a的值。


最后说明一下,不同的指针是不同的,比如下面的两把钥匙是不一样的。因为102-105是连着的,所以第一把钥匙钥匙+1实际地址会加4,而右边的指针对应的只有一个门,+1的时候只会加1,

其实对应的就是int *和char *类型的指针,其中一个长度为4,另一个为1。

这个指针的类型叫做基类型。

10fd024e0139d0a9b65156488666702.png


🔧1.3 数组的指针

数组就是一片连续的空间,数组名称也作为数组的首地址使用。

bd495078abbbfd1cc5a017bc062e27d.png

根据上面提到的指针加1等于加对应的数据长度,所以a+i和&a[i]是完全相同的。

在枚举元素的时候可以这么写:


#include<cstdio>
int main(){
  int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  for(int *p = a; p < a +10;p+)
  printf("%d ",*p);
  return 0;
}


指针的减法


#include<cstdio>
int main(){
  int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  int *p = a;
  int *q = &a[5];
  printf("p = %d ", p);
  printf("q = %d ", q);
  printf("q - p = %d",q - p);
}


输出结果是:p = 2686688 q = 2686708 q - p = 5

会不会感觉震惊?这个q-p竟然不是20???,其实指针的减法是计算两个指针直接差多少个基类型,因为是int所以返回的就是相差多少个int。


🍡1.4 指针数组

了解完了数组额的指针,那么指针数组是什么呢?就是有一片区域保存着钥匙的区域就是,就是指针数组。同时指针数组的名称也做为这片区域的首地址使用。

d1f3bfcbb22061327f7ae31b1afd91b.png

举个栗子🌰

我声明了一个指针数组int *pnums[4]分别对应上图的四把钥匙,那么pnums的值就是201,假如我想访问102的值就是*(pnums[0])就能够访问啦。

注意:int *pnums[10]和int (*punums)[10]是完全不同的。后者代表的含义是这是一个指向长度为10的数组的一个指针。


🍭1.5 高级指针

人类的本质就是套娃。套娃可以生出万千花花世界0.0

f2bde847c87f9b1c07a0128f68e371c.png

其实高级指针就是告诉程序这是一个多少级的间接索引。比如二级指针就是需要进行两次查找值才是最终的数据。三级指针就是需要进行三次取值才是最终的数据。

85e7d5cfd648047102d6479d966ab3b.png

就如上图,那么为啥一定要区分地址和最终的值呢?因为地址的长度和数据长度一般是不一样长的,比如64位机的寻址空间就是64位,而一个int是32位,为了防止出错就会进行区分。

其实高级指针就是多级索引,只有一层一层剥开才能拿到最终的数据啦。


🍬1.6 指针函数

所谓的指针函数,其实就是返回类型是指针的函数。

比如我们需要返回一组数据就需要返回数组的首地址。


int *nums(int k,int * returnnums){
  ...
}


上面的一个函数就返回了一个int类型的指针。一般我们写程序为了知道返回指针的长度会有一个参数returnnums传进去来获得相应的数组长度。


🍶1.7 函数指针

其实函数指针也像上面说的那样,是函数保存的地址。之前的都是数据的地址,但是函数本质上也是内存内的一片区域,所以本质上来说对cpu来说没有太大的区别,所以当然可以有地址啦。

举个栗子


int cmp(cont void *a, const void *b){
  return *((int *)a) > *((int *)b) ? 1 : -1;
}
int main(){
  ...
  qsort(nums,numssize,sizeof(int),cmp);
  ...
}


上面的cmp当做qsort传参的时候就是对应的函数的指针,同样的,函数指针也有不同的基类。qsort要求的基类就是int (*fn) (const void *,const void *),就是一个返回类型为int且传入参数为两个const void*的函数。

不同的基类可能会造成解析错误(类比int 和char 长度不同拿到的数据会出错)。


🍸1.8 最终总结

其实我们可以发现:


指针放在后面就表示某个东西的地址

指针放在前面就表示本身的属性是指针

有没有觉得好记一些呢?



相关文章
|
4月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
90 0
|
2月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
124 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
2月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
179 9
|
2月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
64 7
|
3月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
267 13
|
3月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
90 11
|
3月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
3月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
216 3
|
3月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
3月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
72 1

热门文章

最新文章