zoukankan      html  css  js  c++  java
  • 读书笔记--C陷阱与缺陷(二)

    第二章

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

    1 struct rec
    2 {
    3     int date;
    4     int time;
    5 }
    6 main()
    7 {
    8     ...
    9 }

    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;来实现某些功能,可以这么写,但是代码阅读起来容易产生疑问。

  • 相关阅读:
    好文!悟透JavaScript
    关于“四舍六入五成双/四舍六入五留双/四舍六入五单双”等口诀的实例研究
    第四个:怎么应付在背地里说你坏话的人
    为什么日全食时开始下雨,10分钟后雨又停了。初中物理知识。
    吃萝卜去口气(口臭)
    今天12点34分56秒是一个神奇的时刻
    sharepoint2010人性化的地方员工离职AD账号禁用(个人网站自动提醒上级经理功能)
    指定为添加到网站中的项目显示“新”图标的天数。
    解决sharepoint2010的多行文本框的插入图片—【从sharepoint】的disabled问题
    sharepoint2010的IE6不支持的解决方法
  • 原文地址:https://www.cnblogs.com/chenzhefan/p/7455620.html
Copyright © 2011-2022 走看看