zoukankan      html  css  js  c++  java
  • C陷阱与缺陷(二)

    第二章 语法陷阱

    2.1 理解函数声明

    (*(void(*)())0)();
    任何C变量的声明都由两部分组成:类型以及一组类似表达式的声明符。
    一旦我们知道了如何声明一个给定类型的变量,那么该类型的类型转换符只需要添加一个括号即可的到。
    例如 float (*h)();表示h是一个指向返回值为浮点类型的函数的指针。
    因此(float (*h)())表示一个"指向返回值为浮点类型的函数的指针"的类型转换符。

    第一步假设fp是一个函数指针,那么通过(*fp)()调用fp所指向的函数,可以简写问fp()。
    在表达式(*fp)()中,*fp两侧的括号非常重要,因为函数运算符()的优先级高于单目运算符*。
    如果没有括号则*fp()效果等同于*((*fp)())的简写形式。
    我们本意是(*0)();但是上式并不能生效,因为运算符*必须要一个指针来做操作数。而且这个指针还应该是一个函数指针。
    因此在上式中必须对0作类型转换。

    如果fp是一个指向返回值为void类型的函数的指针,那么(*fp)()的值为void,fp的声明如下:void (*fp)();
    将常数0转型为“指向返回值为void的函数的指针”类型,可以这样写:(void (*)())0

    2.2 运算符的优先级问题

    优先级最高者其实并不是真正意义上的运算符,包括:数组下标、函数调用操作符各结构成员选择操作符。它们都是从左到右结合。
    单目运算符的优先级仅次于前述运算符。单目运算符是从右到左。
    接下来就是双目运算符。其中,算术运算符的优先级最高,移位运算符次之,关系运算符再次之,接着就是逻辑运算符、赋值运算符。
    再下来就是三目运算符即条件运算符。

    任何两个逻辑运算符都具有不同的优先级,每个与比每个或优先级高。
    所有赋值运算符的优先级都是一样的从右到左。
    在所有的运算符中,逗号运算符的优先级最低。

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

    在if或者while语句之后需要紧跟一条语句时,如果此时多了一个分号,那么原来紧跟在if或者while子句之后的语句就是一条单独的语句,与条件判断部分没有了任何关系。
    还有一种情形,当一个声明的结尾紧跟一个函数定义时,如果声明结尾的分号被省略,编译器可能会把声明的类型视作函数的返回值类型。
    例如
    struct log{
    int date;
    int time;
    int code;
    }
    main()
    {
      ...
    }
    上面代码实际的效果是声明函数main的返回值是结构log类型。

    2.4 switch语句

    C语言的switch语句的控制流程能够依次通过并执行各个case部分,要注意使用break语句及时把case中断。
    我们可以在不添加break的部分添加一行注释  /*此处没有break语句*/

    2.5 函数调用

    f();是一个函数调用语句
    f;这个语句计算函数f的地址,却并不调用该函数。

    2.6 悬挂else引发的问题

    else的原则是就近原则。

    C语言允许初始化列表中出现多余的符号,例如
    int das[]={31,28,31,};

  • 相关阅读:
    【转】【C++】【MFC】各种数据类型大小
    【转】【C++】【MFC】关于RADIO BUTTON的使用方法
    【C++】【MFC】创建新的线程函数
    【C++】【MFC】定义全局变量的方法
    【Quartus错误】Internal Error: Sub-system: AMERGE
    【转/TCP协议编程】 基于TCP的Socket 编程
    SQL递归查询(with as)
    SQL查询月、天、周、年(MySql的实例对比)
    sql 基础语句
    经典SQL语句大全
  • 原文地址:https://www.cnblogs.com/tuifeideyouran/p/3139431.html
Copyright © 2011-2022 走看看