​ 独创性并不是首次观察某种新事物,而是把旧的、很早就是已知的,或者是人人都视而不见的事物当新事物观察,这才证明是有真正的独创头脑 —尼采

本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues。

https://github.com/midou-tech/articles

点关注,不迷路!!!

序言

 指针是C语言学习者绕不过的一道坎,也是C语言学习者不得绕过的一道坎。辨别一个人C语言学的好赖就看他对指针的理解怎么样。指针内容也是工作面试经常问到的问题。本文将带你重新认识那个绊倒你的指针,以解大家的心头之惑(恨)。

为什么要学习指针?

 有同学就要说了,既然指针这么难,这么不通俗易懂,为什么要学习他呢?其他高级语言都是把这块基本屏蔽掉了,不在让程序员直接操作指针,这里不直接操作指的是不让程序员用指针进行运算和强转而不是彻底没有了。举个java的例子

Object obj= new Object();
Object sec= obj;
sec = new Object();

 如果你去仔细研究他们的行为,就会发现 obj, sec 都只是一个指向对象的东西,可以为空,也可以修改指向,所以它们其实都是指针,只是 Java 的教材里面不在去提这东西而已,具体原因看我后面讲解便知道了。

​ 继续说为什么学习指针,为什么学习指针就必须要说到指针的优点了。

  • 指针可以直接操作变量地址,所以很灵活。
  • 指针操作会减少很多变量的拷贝使得程序性能提升。
  • 可以动态分配内存。

 这些优点使得很多后台性能要求很高的系统、游戏内核、一些高并发的中间件都是使用C&C++语言开发出来的。比如强大的linux系统、nginx,mysql、redis等等。

 曾经看到一个搞笑的评论,hhh

道生一,一生二,二生三,三生万物

电脑生汇编,汇编生C , C生C++,C/C++生万物

指针是什么?

 其实指针看起来复杂,听起来复杂,学起来复杂,但是总结下来指针到底是个啥,也就一句话。

指针就是地址,指针变量就是一个存放内存地址的变量

 你没看看错,是的就是这么简单明了。通常我们说的指针就约等于说的是指针变量。

指针和内存地址的关系

 很多人不明白指针其实也就是不明白内存地址,所以要想明白指针必须先明白指针和内存之间的关系。在讲内存和指针之间的关系之前先说下什么是内存。

 先明白一个问题,什么是内存?编程人员常说的内存指的是什么?

​ 内存是电脑的一个硬件组成部分。从单片机的组成我们可以看到,CPU、内存和输入输出接口,就组成一个完整的电脑,其他统统属于外设。内存是可以被CPU通过总线进行操作的,也就是与CPU之间有总线相连接的。电脑所有的输入输出,都是要从内存来实现的。内存包括只读内存ROM和读写内存RAM,但在个人电脑(PC)中,我们通常所说的内存,是指读写内存。

​ 程序人员常说的内存其实是虚拟内存,程序直接操作的是虚拟内存而不是真正的物理内存。

纳尼


程序都是操作的虚拟内存? 那虚拟内存是个啥东西?

 这里先给大家画张C语言程序的内存布局图。关于进程和内存管理会在后面的文章讲出来,记得微信搜索 龙跃十二 点关注。


内存布局图

 这个图很好的描述了内存地址的布局,指针变量里面存放的地址也就是这个内存地址。顺便说下啥是内存地址,用十六进制表示出来的一串数字编号(就好比你家的门牌号),只是这个数字是给内存标号的。32位系统下这个编号是4byte(32个bit)表示的,64位系统下是8byte(64bit)表示的。(这个小问题面试会被问到的)

如何使用指针?

指针的声明

int *p;
char *p1;
float *p2;

 声明还是很简单,指针的类型 * 变量名即可声明一个指针变量。

int num = 5;
int *p = #

 此时就是一个int类型的指针变量指向一个int变量,画个图解释下。


 以很清楚的看到指针p存放着变量num的地址,我们通常说指针p指向变量num,当p知道变量num之后,p就可以对变量num为非作歹了,比如

int main(){
    int num = 5;
    int *p = #
    printf("*p=%d,num=%d\n",*p,num);  //此时num的值就变为5
    p+=1;
    printf("*p=%d\n",*p);    //此时p指向了哪里?这句代码会不会报错?

指针的大小和类型

 从上面的声明实例可以看到我定义了三种类型的指针,可以看出指针是有类型的。这里有同学就有疑问了,不是存放内存地址的么,内存地址不就是一串十六进制表示的数字么(其实底层都是二进制),哪来的什么类型一说呢,为什么又需要类型呢?

 这个疑问很好,我当时学习的时候也是很疑惑。首先我们明白了指针是一个存放地址的变量,明白这点还不够还必须理解另外一个问题就是

字节(Byte)是用于计量存储容量的一种单位,每一个字节由8位组成(1Byte = 8bit)。地址可以理解为在一片内存中,每个字节(Byte)的编号。

 所以很多人肯定会明白了,指针存放的是一个变量的首个字节的地址,那么问题来了。

int a = 5; 
int *p = &a;

 我们声明指针p指向变量a的地址,也就是说指针p里面存放着变量a的首地址,在32位平台下,int a 是4字节,指针去取a的值的时候找到的是a的首地址,那怎么拿到变量a,聪明的同学已经恍然大悟,是的,没错,所以我们的指针需要类型的,编译器去取指针指向的内容时候会根据指针的类型去取。画个图如下


 此刻我相信你对指针已经有了很高的理解了。指针的大小很好理解 就是存放地址的范围,地址的范围是操作系统地址线的根数决定,所以指针的大小是随操作系统的寻址范围决定的,一般32位系统地址总线也是32根,寻址范围是2^32次方

 顺便说下32位操作系统和64位操作系统的区别在哪里,系统的位数代表运算能力,所谓32位就是能计算的字长是32位的,64位系统能计算的字长是64位。处理器的字长越大,说明它的运算能力越强。

点赞

重新认识C语言的指针(上)的更多相关文章

  1. C语言之漫谈指针(上)

    C语言之漫谈指针(上) 在C语言学习的途中,我们永远有一个绕不了的坑,那就是--指针. 在这篇文章中我们就谈一谈指针的一些基础知识. 纲要: 零.谈指针之前的小知识 一.指针与指针变量 二.指针变量的 ...

  2. 浅谈c语言的指针

    对于非计算机专业的同学,c语言的指针往往就是老师的一句“指针不考“就带过了.c语言的指针号称是c语言的灵魂,是c语言中最精妙的部分. 指针本质上也是变量,也就是一段内存,只是他的特殊之处是他存储的数据 ...

  3. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  4. C语言二重指针与malloc

    (内容主要源于网上,只是加入了些自己的剖析) 假设有一个二重指针: char **p; 同时有一个指针数组 char *name[4]; 如何引用p呢? 首先我们有程序代码如下 #include &l ...

  5. C语言函数指针基础

    本文写的非常详细,因为我想为初学者建立一个意识模型,来帮助他们理解函数指针的语法和基础.如果你不讨厌事无巨细,请尽情阅读吧. 函数指针虽然在语法上让人有些迷惑,但不失为一种有趣而强大的工具.本文将从C ...

  6. 为什么C/C++语言使用指针

    这是参加面试时,面试官问的一道开放性题目. 问题是:为什么C/C++语言使用指针? 这个问题一问出来,直接被面试官秒杀了,面试官大神,你怎么不按套路出牌啊? 说好的malloc和new的区别呢?说好的 ...

  7. C语言的指针变量

    C语言的指针变量 在C语言中,变量是固定范围的存储空间,它存储的是赋给他的值, 比如: ; /* 这里是定义一个整型变量a,并把12这个值存储在a的地址空间上 这个地址空间是系统随机分配的,对用户是透 ...

  8. [C语言]进阶|指针与字符串

    ------------------------------------------------------------------------------------ 回顾:[C语言]指针与字符串 ...

  9. go语言学习--指针的理解

    Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, fu ...

随机推荐

  1. MongonDB指令汇总

    MongoDB特点使用不存在的对象,就等于你在创建这个对象(库,表,记录) MongoDB服务器/客户端相关 (记得把配置环境变量bin,MongonDB安装后bin在C盘的programfile-- ...

  2. 在 CentOS 7.3 上安装 nginx 服务为例,说明在 Linux 实例中如何检查 TCP 80 端口是否正常工作

    CentOS 7.3 这部分以在 CentOS 7.3 上安装 nginx 服务为例,说明在 Linux 实例中如何检查 TCP 80 端口是否正常工作. 登录 ECS 管理控制台,确认实例所在安全组 ...

  3. [转载] linux find 命令

    转载自 http://www.jb51.net/os/RedHat/1307.html Linux下find命令在目录结构中搜索文件,并执行指定的操作. Linux下find命令提供了相当多的查找条件 ...

  4. linux readv 和 writev

    Unix 系统已经长时间支持名为 readv 和 writev 的 2 个系统调用. 这些 read 和 write 的"矢量"版本使用一个结构数组, 每个包含一个缓存的指针和一个 ...

  5. 如何在 centos 7.3 上安装 caffe 深度学习工具

    有好多朋友在安装 caffe 时遇到不少问题.(看文章的朋友希望关心一下我的创业项目趣智思成) 今天测试并整理一下安装过程.我是在阿里云上测试,选择centos 7.3 镜像. 先安装 epel 源 ...

  6. P1082 数列分段

    题目描述 对于给定的一个长度为 \(N\) 的正整数数列 \(A_i\) ,现要将其分成连续的若干段,并且每段和不超过 \(M\) (可以等于 \(M\) ),问最少能将其分成多少段使得满足要求. 输 ...

  7. SELECT command denied to user ''@'%' for column 'xxx_id' in table 'users_xxx' 权限问题

    问题的原因是:最主要是权限的问题. 大概说下 ,我导数据库时提示错误:SELECT command denied to user ''@'%' for column 'xxx_id' in table ...

  8. 【mac】Mac 终端如何切换成管理员用户

    方法1.打开终端输入 sudo su  然后回车 Password:  ------(输入root密码即可) sh-3.2# --------    (输入执行的命令即可,例如 npm i -g np ...

  9. PHP mysql扩展整理,操作数据库的实现过程分析

    相关文章:PHP mysqli扩展整理,包括面向过程和面向对象的比较\事务控制\批量执行\预处理   PHPmysqli扩展整理,包括面向过程和面向对象的比较\事务控制\批量执行\预处理 从某种程度上 ...

  10. Vue中通过属性绑定为元素绑定style行内样式

    1.直接在元素上通过:style的形式,书写样式对象 2.将样式对象定义在data中,并直接引用到:style中 3.在:style中通过数组,引用多个data上的样式对象