豆瓣9.0,百万程序员的宝藏书,C语言进阶必看

Posted 异步图书

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了豆瓣9.0,百万程序员的宝藏书,C语言进阶必看相关的知识,希望对你有一定的参考价值。



著名作家肯尼斯·里科(Kenneth Reek)说过:是指针使C语言威力无穷。


指针为什么如此重要?C语言圈内有一句经典的自嘲:C语言就只有指针可以用了。


如果你干掉struct、干掉union、干掉数组、甚至你把if-while都干掉、只留下malloc和goto,最多就是程序难写一点而已;但如果你把指针干掉,那C语言就完了。


你会用指针、用好指针之后,就能发挥C语言的强大威力;如果你不会用,C语言其实不会比其他的任何一种语言好。所以当你想要进阶你的C语言能力时,对指针有一个深入而完整的理解是必不可少的。这也正是《C和指针》面世12余年,能够被无数程序员奉为宝藏书的原因。


这本书通过对指针的基础知识和高级特性的探讨,帮助程序员把指针的强大功能融入到自己的程序中去。全书共18章,覆盖了数据、语句、操作符和表达式、指针、函数、数组、字符串、结构和联合等几乎所有重要的C编程话题。


豆瓣9.0,百万程序员的宝藏书,C语言进阶必看


《C和指针》在豆瓣上有9.0的评分,海量好评当中,不少读者都笑侃作者是个“起名废”,因为这本书的涵盖的内容其实大大超过了指针。毕竟想要成为一名优秀的C语言程序员,进阶必学知识点还真是不少。下面我们就来一起看看吧~


C语言进阶应该学什么


当你掌握了C语言的基本语法、或是具备一定的编程经验后,千万不要因为“为什么循环很重要”以及“何时需要使用if语句”等肤浅问题耽误进程,不论你想要进阶的原因是钻研C语言本身、还是想要以C为基础得到更好的职业发展,以下5点都是很必要的:


一:操作符和表达式

C提供了我们希望编程语言应该拥有的所有操作符,它甚至提供了一些令人意想不到的操作符。事实上,C被许多人所诟病的一个缺点就是它有品种繁多的操作符——C的这个特点使它很难被精通。


但是,C的许多操作符具有其他语言的操作符无可抗衡的价值,这正是C适用于开发范围极广的应用程序的原因之一。C语言进阶,搞清楚操作符优先级和算术转换是重要的一课。


二:数据、结构和联合以及动态内存分配

程序对数据进行操作,数据又经常以成组的形式存在。例如,雇主必须明了每位雇员的姓名、年龄和工资。如果这些值能够存储在一起,访问起来会简单一些。但是,如果这些值的类型不同,则无法存储于同一个数组中。在C中,使用结构可以把不同类型的值存储在一起。


数组的元素存储于内存中连续的位置上。当一个数组被声明时,它所需要的内存在编译时就被分配。但是,也可以使用动态内存分配在运行时为它分配内存。那么什么时候应该使用动态内存分配?怎样进行动态内存分配?想成为一名合格的C语言程序员,这些你都了解了吗?


三:字符串、字符和字节

字符串是一种重要的数据类型,但是C语言并没有显式的字符串数据类型,因为字符串以字符串常量的形式出现或者存储于字符数组中。字符串常量很适用于那些程序不会对它们进行修改的字符串。处理字符串和字符的库函数,以及一组既可以处理字符串也可以处理非字符串数据的相关函数是进阶C语言的一道不小的门槛。


四:预处理器

编译一个C程序涉及很多步骤。其中第一个步骤被称为预处理(preprocessing)阶段。C预处理器(preprocessor)在源代码编译之前对其进行一些文本性质的操作。它的主要任务包括删除注释、插入被#include指令包含的文件的内容、定义和替换由#define指令定义的符号,以及确定代码的部分内容是否应该根据一些条件编译指令进行编译。


五:指针


新手面对指针的常见问题


C语言的指针很重要,但新手进阶C语言时,指针相关的问题往往是最多的,这里给大家挑选了两个常见问题,看看你对这几点了解吗?


一、未初始化和非法的指针

下面这个代码段说明了一个极为常见的错误:


豆瓣9.0,百万程序员的宝藏书,C语言进阶必看


这个声明创建了一个名叫a的指针变量,后面那条赋值语句把12存储在a所指向的内存位置。但是究竟a指向哪里呢?


我们声明了这个变量,但从未对它进行初始化,所以没有办法预测12这个值将存储于什么地方。从这一点看,指针变量和其他变量并无区别。如果变量是静态的,它会被初始化为0;如果变量是自动的,它根本不会被初始化。无论是哪种情况,声明一个指向整型的指针都不会“创建”用于存储整型值的内存空间。


所以,如果程序执行这个赋值操作,会发生什么情况呢?





二、高级声明

在使用更高级的指针类型之前,我们必须观察它们是如何声明的。


我们可以来看几个简单的例子:


int        f();

它把f声明为一个函数,它的返回值是一个整数。旧式风格的声明对函数的参数并未提供任何信息。它只声明f的返回值类型。现在将使用这种旧式风格,这样例子看上去简单一些,后面再回到完整的原型形式


int    (*f)();

确定括号的含义是分析这个声明的一个重要步骤。这个声明有两对括号,每对的含义各不相同。第2对括号是函数调用操作符,但第1对括号只起到聚组的作用。它迫使间接访问在函数调用之前进行,使f成为一个函数指针,它所指向的函数返回一个整型值。


函数指针?是的,程序中的每个函数都位于内存中的某个位置,所以存在指向那个位置的指针是完全可能的。


int        *(*f)();

它和前一个声明基本相同,f也是一个函数指针,只是所指向的函数的返回值是一个整型指针,必须对其进行间接访问操作才能得到一个整型值。


通过以上不难看出,指针虽然很强大,与之相伴的风险却也不小。就像指甲锉和链锯,链锯可以更快地切割木材,但链锯更容易让人受伤,而且伤害常常来得极快,后果也非常严重。


指针就像链锯一样,如果使用得当,它们可以简化算法的实现,并使其更有效率;如果使用不当,它们就会引起错误,导致细微而令人困惑的症状,并且极难发现原因。所以对指针只是略知一二便放手使用是件非常危险的事。


想要学好指针,最好的办法就是有一位导师在身后注视你的工作,时不时给你一些提示和警告。导师是谁?当然是它豆瓣9.0,百万程序员的宝藏书,C语言进阶必看


豆瓣9.0,百万程序员的宝藏书,C语言进阶必看

C和指针