第二章

1. 理解函数声明

书中分析了复杂的类型声明方式,也说明了使用typedef声明会更好理解,推荐大家使用typedef进行函数声明。

书中类型分析一层一层挖掘,让读者可以理解多层嵌套的类型含义,有时间的读者可以去看看,笔者不再重复。

既然书中推荐使用typedef进行函数声明,我们就来研究下typedef:

typedef主要用于定义一种类型/结构体的别名。

从字面上看和C的宏定义 #define 挺像的,但是define只是简单的参数替换,如果不注意括号很容易产生预期之外的错误。

在指针类型声明时最好使用typedef,如下:

typedef char* PCHAR;

#define dpchar char*;

PCHAR p1,p2;

dpchar p3,p4;

上述语句中,p1,p2,p3可以被成功定义为char*,但是p4被定义为char(char* p3,p4;)。

对于结构体,一般定义为:

typedef struct STUDENT_ST

{

int id;

char name;

} student;

student st1;//代替struct STUDENT_ST st1,声明更加简单

typedef可高效解决平台无关的数据类型,这对公司非常重要,因为不同的项目背景可能使用的系统平台不尽相同,统一的管理数据类型可以避免错误。

如 typedef long double LONGNUM;

或 typedef long LONGNUM;

在跨平台时就可以通过修改typedef来切换数据类型,而不用修改源码,想象下如果修改每个源码里的类型该是多大的工程。。。

其实,还可以结合typedef使用bit field方式自定义字节长度的类型,下次有机会详细说明吧~~

typedef另一个使用较多的就是书中提到的声明复合类型:

如书中:(* (void (*) ()) 0) ();

可以改写为:typedef void (*pfun) ();

(* (pfun) 0) ();

2. 运算符优先级

其实记不清运算符优先级的时候怎么办,加括号呗,最多就是括号多了理解起来费时点~

来看看书中推荐的优先级记法:

第一优先级: ()  []  ->  .

其实是括号和调用操作符,很好理解,书中认为不用记,确实如此!

第二优先级: !  ~  ++  --  - (type)  *  &  sizeof

由于第一优先级好理解,单目运算符可认为是最高优先级。

但要注意两点:

  1. 对于 *p() ,因为第一优先级更高所以被解释为 *(p()),要正确调用指针p指向的函数应为 (*p)() 。
  2. 单目运算符是自右向左结合的(与人看文字方向相反)。所以如 *p++ 会被解释为*(p++),加1的是p值;写为 (*p)++,加1的是p指向对象的值;虽然都是取出p指向对象的值。。。。

第三优先级:  *  /  %  -  +  (算术运算符)

第四优先级: <<  >>  (移位运算符)

第五优先级: <  <=  >  >=  ==  !=  (关系/比较运算符)

第六优先级: &  |  ^  (逻辑/位运算符)

第七优先级: &&  ||  (逻辑运算符)

第八优先级: ? :  (条件运算符)

注意:关系/比较运算符中,==  != 的优先级低于其他关系运算符。如书中例子: a < b == c < d  即  (a<b) == (c<d)

逻辑运算符优先级也不相同,一般是”与”>”或”,即 &>^>|>&&>||

所有的赋值运算符(=)优先级一样,但是自右向左结合!!

3. 注意分号

主要注意if  while  struct声明。其实这些都比较简单,但是笔者确实遇到过这种问题,当时笔者在if();后加了分号,程序结果一直不对但是检查了很久才发现。。。

struct声明后紧跟函数声明时缺少分号很危险,书中提到编译器会把声明类型视为函数的返回值类型。如:

 struct rec
{
int date;
int time;
}
main()
{
...
}

struct rec的声明结尾没有分号,可能变为main函数的返回类型。。。

笔者对该程序进行了build,出现了两个warning和1个error:

第一个warning说:main函数的返回类型不是int;

第二个warning说:控制到达非void函数的结尾。通俗说就是应该带有返回值的函数结尾可能无返回值。

error说:类型不匹配,当要返回int却要求返回struct rec

看来优秀的IDE(codeblocks)还是可以避免这类错误的!

4. switch语句

书中强调C语言的switch语句能依次通过并执行各个case部分,所以若只想执行一个case要加break;

如:switch (color)

{

case 1 : printf(“red”);

case 2 : printf(“yellow”);

case 1 : printf(“blue”);

}

假设color取值2,最后程序打印  yellowblue

因为case2,case3都执行了,所以要加break;

当然如果你想通过刻意去掉break;来实现某些功能,可以这么写,但是代码阅读起来容易产生疑问。

读书笔记--C陷阱与缺陷(二)的更多相关文章

  1. 读书笔记--C陷阱与缺陷(七)

    第七章 1.null指针并不指向任何对象,所以只用于赋值和比较运算,其他使用目的都是非法的. 误用null指针的后果是未定义的,根据编译器各异. 有的编译器对内存位置0只读,有的可读写. 书中给出了一 ...

  2. 读书笔记--C陷阱与缺陷(一)

    要参与C语言项目,于是作者只好重拾C语言(之前都是C++,还是C++方便). 看到大家都推荐看看  C陷阱与缺陷(C traps and pitfalls),于是好奇的开始了这本书的读书之旅. 决定将 ...

  3. 读书笔记--C陷阱与缺陷(三)

    第三章 1. 指针与数组 书中强调C中数组注意的两点: 1)     C语言只有一维数组,但是数组元素可以是任何类型对象,是另外一个数组时就产生了二维数组.数组大小是常数(但GCC实现了变长数组..) ...

  4. 读书笔记--C陷阱与缺陷(六)

    第六章 1.预处理器:预处理器先对代码进行必要的转换处理,简化编程者的工作. 它的重要原因有以下两点: a. 假如要将程序中出现的所有实例都加以修改,但希望只改动程序一处数值,重新编译实现. 预处理器 ...

  5. 读书笔记--C陷阱与缺陷(五)

    第五章 第五章干货也偏少,但是几个练习题还不错,写出来大家分享下: 1.当一个程序异常终止时,程序输出的最后几行常常会丢失,原因是什么? 我们能够采取怎么样的措施来解决这个问题? 答:因为异常终止的程 ...

  6. 读书笔记--C陷阱与缺陷(四)

    第四章 1. 连接器 C语言的一个重要思想就是分别编译:若干个源程序可在不同的时候单独进行编译,恰当的时候整合到一起. 连接器一般与C编译器分离,其输入是一组目标模块(编译后的模块)和库文件,输出是一 ...

  7. 读书笔记-JavaScript面向对象编程(二)

    第5章 原型 5.1 原型属性(所有函数拥有一个prototype属性,默认为空对象) 5.1.1 利用原型添加方法和属性 function Gadget(name,color){ this.name ...

  8. Spring读书笔记-----使用Spring容器(二)

    一.使用ApplicationContext 前面介绍了,我们一般不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器,它增强了BeanFa ...

  9. (转)Spring读书笔记-----使用Spring容器(二)

    一.使用ApplicationContext 前面介绍了,我们一般不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器,它增强了BeanFa ...

随机推荐

  1. 初涉算法——C++

    一.sstream头文件运用 题目:输入数据的每行包括若干个(至少一个)以空格隔开的整数,输出每行中所有整数之和. #include<iostream> #include<cstri ...

  2. 基于jmeter,jenkins,ANT接口,性能测试框架

    背景 公司计划推接口和性能测试,搭建这个性能测试框架框架是希望能够让每个人(开发人员.测试人员)都能快速的进行性能,接口测试,而不需要关注性能测试环境搭建过程.因为,往往配置一个性能环境可能需要很长的 ...

  3. dubbo搭建例子

    现在很多公司用到dubbo,使用起来是很快就学会了.真的要熟悉它还是要花点功夫的. 前面尝试看了些它的源码,这里为了调试源码,先打搭一个能跑的项目,顺别分享出来,以便刚像学习的朋友节约时间,毕竟时间至 ...

  4. 工具 | 代码调试利器fiddle介绍

    我们开发的系统运行在用户的环境上,为了保护我们的代码和提升性能,前端javascript是经过压缩的.压缩的代码难于定位,当前只有chrome对压缩的代码支持格式化,但是变量和函数简化后,定位依然困难 ...

  5. ubuntu上安装nginx+mysql+php5-fpm(PHP5 - FastCGI Process Manager)

    题外话:由于近段时间测试环境ssh链路质量不大好,经常短线.故我把整个安装过程放到screen里去执行,以防止断线中断了安装过程.执行screen -S install,这样断线后,只要再执行scre ...

  6. Infer 在 Mac 上的安装和环境配置

    Infer 在 Mac 上的安装和环境配置 Infer 介绍 Infer 是一个静态分析工具.Infer 可以分析 Objective-C, Java 或者 C 代码,报告潜在的问题. 任何人都可以使 ...

  7. sping 框架学习之——初始篇

    sping框架学习: 1,什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以 ...

  8. MySQL优化 - 性能分析与查询优化

    优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载选择合理的硬件配置等. 1.性能分析 性能分析包含 ...

  9. Java利用内存映射文件实现按行读取文件

    我们知道内存映射文件读取是各种读取方式中速度最快的,但是内存映射文件读取的API里没有提供按行读取的方法,需要自己实现.下面就是我利用内存映射文件实现按行读取文件的方法,如有错误之处请指出,或者有更好 ...

  10. Social Network Analysis的Centrality总结,以及networkx实现EigenCentrality,PageRank和KatzCentrality的对比

    本文主要总结近期学习的Social Network Analysis(SNA)中的各种Centrality度量,我暂且翻译为中心度.本文主要是实战,理论方面几乎没有,因为对于庞大的SNA,我可能连门都 ...