• C语言缺陷及陷阱读书笔记(二)


    语法陷阱##

    2.1 理解函数声明###

    任何C变量的声明都由两部分组成:类型以及一组类似表达式的声明符(declarator)。

    //表示该函数的返回值是一个指向浮点数的指针
    float *g();
    
    
    ///表示h是一个指针,h所指向的函数的返回值为浮点类型
    float (*h)();
    
    //表示返回值为浮点类型的函数的指针
    (float(*)());
    

    ((void()())0()表示在计算机启动时,硬件将调用首地址为0位置的子例程。

    分析表达式 ((void()())0()

    1. 假设变量fp是一个函数指针,调用该函数指针指向的函数的调用方法为:

      (*fp)()

    2. 找到一个恰当的表达式来替换fp,对(*fp)()进行转换为:指向返回值为void类型的函数的指针:

      void (*fp)()

    3. 调用存储位置为0的子例程

      void (fp)()
      (
      fp) ();

    4.对常数0转型为“指向返回值为void的函数的指针”类型,可写成:(void ()()) 0,用(void ()()) 0替代fp,得到(void()())0 ()

    5.通过tyepdef可以简化:
    typedef void (funcptr) ();
    (
    (funcptr)0) ();

    2.2 运算符的优先级问题###

    1.函数调用的优先级要高于单目运算符的:
    p为一个函数指针,要调用p所指向的函数:(*p) ()

    2.单目运算符是自右向左结合:
    p++会被编译成(p++),即取指针p所指向的对象,然后将p递增1

    3.任何一个逻辑运算符的优先级低于任何一个关系运算符

    4.移位运算符的优先级比算术运算符要低,但是比关系运算符要高

    5.任何两个逻辑运算符都具有不同的优先级。所有的按位运算符优先级要比顺序运算符的优先级高,每个“与”运算要比相应的“或”运算符的优先级要高。按位异或运算符的优先级介于按位与运算符和按位或运算符之间。

    2.3 注意作为语句结束标识的分号###

    if(x[i]>big);
        big=x[i];
    

    if判断语句多写了一个分号,则这个语句单独成为一个语句。相当于语句后多了一个空中括号{}

    if(n<3)
        return
    logrec.date=x[0];
    logrec.time=x[1];
    logrec.code=x[2];
    

    第三,四行多了分号,前三行自成一个语句块。导致程序没能达到预期结果。

    struct logrec
    {
        int date;
        int time;
        int code;
    
    }
    int main(void)
    {
        .....
    }
    

    在第一个}与紧随其后的函数main定义之间,遗漏了一个分号。上面代码实际的效果是声明函数main的返回值是结构logrec类型。

    2.4 switch语句###

    C语言的switch语句的控制流程能够依次通过并执行各个case部分。
    程序员容易遗漏各个case部分的break语句。但有时候刻意隐去break能达到不一样的效果:
    加减法程序:

    case SUBTRACT:
          opnd2=-opnd2;
    case ADD:
          .......
    

    2.5 函数调用###

    在函数调用即使函数不带参数,也应该包括参数列表:

    f()是一个函数调用语句,而f却不是。

    2.6 “悬挂”else引发的问题###

    if(x==0)
        if(y==0) error();
    else{
            z=x+y;
            f(&z);
    }
    

    这段代码当x等于0时,如果y也等于0就进行错误处理,y不等于0的情况下,将x与y之和赋给z,然后以z的地址为参数来调用函数f。但是在程序运行的时候却发生错误,由于C语言中的else始终与同一对括号内最近的未匹配的if结果,所以程序运行时是以下列缩进进行的:

    if(x==0){
        if(y==0)
             error();
        else{
            z=x=y;
            f(&z);
    }
    }
    

    如果x不等于0,程序将不会做任何处理。

    改进:

    有两种方法可以解决这个问题:

    1.将第二个if语句用括号封装起来,这样就不会与else进行结合了。(个人觉得这种方法比较可行)。
    2.通过宏定义来解决问题。

  • 相关阅读:
    微信内置浏览器的JsAPI(WeixinJSBridge)
    跨域请求 jQuery的ajax jsonp的使用
    Window10设置技巧
    Oracle命令集
    通过sql server 连接mysql
    深入 AngularUI Router
    解决Web部署 svg/woff/woff2字体 404错误
    C#四舍五入、上取整、下取整
    SQL语句:两个时间区间段,只要有交集,就能筛选出来
    url传参中文乱码问题
  • 原文地址:https://www.cnblogs.com/luyoujun/p/4824066.html
Copyright © 2020-2023  润新知