你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

你知道C语言和指针之间什么关系吗?

[复制链接]
gaosmile 发布时间:2020-3-16 11:22

很多编程语言都以 “没有指针” 作为自己的优势来宣传,然而,对于C语言,指针却是与生俱来的。

        那么,什么是指针,为什么大家都想避开指针。

        很简单, 指针就是地址,当一个地址作为一个变量存在时,它就被叫做指针,该变量的类型,自然就是指针类型。

        指针的作用就是,给出一个指针,取出该指针指向地址处的值。为了理解本质,我们从计算机模型说起。

        宏观看来,计算机可以分为两类:

        存储-执行计算机。
        这类机器典型的例子就是我们平时使用的计算机,有一个CPU,有一个内存,CPU仅包含运算逻辑,所有的指令和数据都在内存中,内存仅供存储,不包含任何运算组件。
        现场编程计算机。
        这类机器的典型例子就是ASCI电路FPGA这种。直接针对特定的需求构建逻辑电路,然而,由于存在笛卡尔积的问题,不太适合通用计算。
        我们看我们平时使用的存储-执行模型的计算机工作模式:

        CPU在地址总线上发射一个地址到内存。
        内存把特定地址对应的数据返回到数据总线。
        看起来,通用计算机就是通过指针完成所有工作的。CPU没有能力直接操作内存里的值,它必须做以下的操作以迂回:

        从特定地址A0取出值V0。
        对V0进行加工运算生成V1。
        将V1存入特定地址A1。
        太初,人们就是按照以上的这么个逻辑编程的,这就是汇编语言:

        mov -0x4c(%rbp),%ebx
        然而,这样太麻烦了,C语言随着简单通用的UNIX操作系统而生,下面的语句看起来更加方便:

        int a = 10;
        char *p = &a;
        *p = 13;
       
        C语言直接映射了CPU的工作方式,而且是用极其简单的方式,这就是C语言的艺术。

        这就是C指针的背景。在那个年代,人们还没有渴望计算机帮助完成更复杂的业务逻辑,人们只是希望用一种更加简单的方式抽象出计算机的行为,最终的结晶,就是C语言。

        于是,我们说,C语言的精华就是指针,指针是C语言的一切。我们可以没有if-else语言,我们可以没有switch-case语句,我们可以不要while,我们不要for,但我们必须有指针。

        是的,我们可以用指针函数的状态矩阵代替if-else之类:

        int (*routine)[...]();
        ...
        condiTIon = calc(...);
        rouTIne[condiTIon](argv);
       
        我们用状态矩阵成功规避了if-else…可以看到,还是用的指针。

        …

        指针是存储-执行模型的计算机工作的必要条件!

        我们再看存储-执行模型的计算机的工作方式:

        给定一个地址,CPU就可以取出该地址的数据。
        给定一个地址,CPU就可以写入该地址一个值。
        这意味着什么?

        只要想让CPU正常工作,就必须暴露整个内存地址空间给CPU,否则CPU就是一堆毫无用处的门电路,换句话说, 一切来自内存! 操作内存就必然要用指针!

        其实,C语言就是简化版的汇编语言。最终,C语言接力汇编用指针创造了世界。

        不管怎么样,C语言是面向计算机的编程语言,而不是面向业务的编程语言,它映射了计算机的工作方式而不太善于描述业务逻辑,因此,C语言深受黑客,编程手艺人这种计算机本身的爱好者喜爱,却不被业务程序员待见,因为摆弄指针确实太繁琐复杂了,一不小心就会出错。

        存储-执行模型的问题在于,要设计复杂的带外机制防止内存被任意访问,由此而来的就是复杂的分段,分页,访问控制,MMU等机制,当然,这些机制和CPU依靠指针访问内存的工作方式并不冲突。

        把C语言指针用的最绝的应该就是Linux内核的嵌入式链表 struct list_head 了:

        struct list_head {
        struct list_head *next, *prev;
        };
       
        它可以代表一切,它通过C指针完美诠释了OOD,list_head是世界的基类!

        通过container_of宏,list_head可以转换为任意对象:

        /**
        * container_of - cast a member of a structure out to the containing structure
        * @ptr: the pointer to the member.
        * @type: the type of the container struct this is embedded in.
        * @member: the name of the member within the struct.
        *
        */
        #define container_of(ptr, type, member) ({ \
        void *__mptr = (void *)(ptr); \
        BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
        !__same_type(*(ptr), void), \
        "pointer type mismatch in container_of()"); \
        ((type *)(__mptr - offsetof(type, member))); })
        这个转换背后的依赖,正是指针:

       

        然而,C语言依然对业务编程不友好,前面说了,C语言映射的就是计算机工作方式本身,若想用好C语言,就必须要懂计算机原理,这并不是业务程序员的菜,业务程序员只是编写业务逻辑,并不在乎计算机是如何工作的。

        曾经,计算机还是一群痴迷于技术本身的极客们的玩具,计算机是属于他们的,他们用C编程,用Perl/Python/Bash粘合二进制程序。进入互联网时代,随着越来越复杂的业务逻辑出现,越来越多的职业程序员开始成了多数派,他们开始使用更加业务友好的语言,Java,Go便成功了。

        不能说这些业务编程语言没有指针,只是它们隐藏了指针而已,它们对程序员暴露了更加对业务友好的编程接口和语法,自己在底层处理指针问题,仅此而已。指针是客观存在的,只要你使用的是存储-执行模型的计算机,指针就是一切。


收藏 评论0 发布时间:2020-3-16 11:22

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版