C陷阱与缺陷之语法陷阱

    2.1理解函数声明

    不论什么C变量的声明都由两部分组成:类型以及一组类似表达式的声明符号。比如

    float f;

    这个声明的含义是:当对其求值时,表达式f和g的类型为浮点数类。由于声

    明符与表达式的相似。所以我们也能够在声明符中随意使用括号:

    float ((f))

    这个声明的含义是:当对其求值时,W)的类型为浮点类型,由此能够推知,f也是浮点类型。类似的。

    float *g(),(*h)();

    表示*g()与(*h)()是浮点表达式。

    由于()结合优先级高于*。*g()也就是*(g()):g是一个函数。该函数的返回值类型为指向浮点数的指针。同理,能够得出h是一个函数指针,h所指向函数的返回值为浮点类型。

    理解了上面的知识后。我们就能够分析signal函数了,signal函数的原型为:

    #include <signal.h>

    void ( *signal ( int signo ,void (*func)(int) ) ) ( int );

    signal函数原型说明该函数须要两个參数,返回一个函数指针,而该指针所指向的函数须要一个整型參数,无返回值。

    第一个參数signo是一个整数,第二个參数是函数指针。它所指向的函数须要一个整型參数,无返回值。用自然语言描写叙述也就是要向信号处理程序传递一个整型參数,而它却无返回值。当调用signal设置信号处理程序时,第二个參数是指向该函数(也就是信号处理程序)的指针。

    signal的返回值则是指向之前的信号处理程序的指针。

    2.2运算符的优先级问题

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGFuY2h1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

    优先级最高者事实上并非真正意义上的运算符,包含:数组下标、函数调用操作符各结构成员选择操作符。它们都是白左于右结合。因此a.b.c的含义是(a.b).c,而不是a.(b.c)。

    单目运算符的优先级仅次于前述运算符。在全部的真正意义上的运算符中。它们的优先级最高。

    由于函数调用的优先级要高于单目运算符的优先级,所以假设p是一个函数指针。要调用p所指向的函数,必须这样写:(*p)()。假设写成*p()。编译器会解释成*(p())。类型转换也是单目运算符。它的优先级和其它单目运算符的优先级一样。单目运算符是白右至左

    结合,因此*p++会被编译器解释成*(p++),即取指针p所指向的对象。然后将p递增1:而不是(*p)++,即取指针p所指向的对象,然后将该对象递增1。

    优先级比单目运算符要低的,接下来就是双目运算符。

    在双目运算符中,算术运算符的优先级最高。移位运算符次之,关系运算符再次之,接着是逻辑运算符。赋值运算符,最后是条件运算符(为三目运算符)。

    我们须要记住的最重要的两点是:

    1.不论什么一个逻辑运算符的优先级低于不论什么一个关系运算符。

    2.移位运算符的优先级比算术运算符要低,可是比关系运算符要高。

    在全部的运算符中,逗号运算符的优先级最低。这一点非常easy记住,由于逗号运算符经常使用于在须要一个表达式而不是一条语句的情形下替换作为语句结束标志的分号。

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

    在C程序中假设不小心多写了一个分号可能不会造成什么不良后果:这个分号或许会被视作一个不会产生不论什么实际效果的空语句;或者编译器会由于这个多余的分号而产生一条警告信息,依据警告信息的提示可以非常easy去掉这个分号。一个重要的例外情形是在if或者while语句之后须要紧跟一条语句时。假设此时多了一个分号,那么原来紧跟在if或者while了句之后的语句就是一条单独的语句。与条件推断部分没有了不论什么关系。考虑以下的

    这个例了:

    if(x [i]>big);

    big=x[i];

    2.4 switch语句

    switch语句中要注意case后面加break。这样才干起到控制的作用。当然有些时候,有益不加break以达到某种效果。

    2.5悬挂else引发的问题

    C语言中if else配对规则:else始终同一对括号内近期的为匹配的if结合。

    比如这样就可能和违背编程者的本意:

    if(x==0)

    if(y==0) error();

    else{

    z = x + y;

    }

    缩进后。成这样

    if(x == 0)

    if(y == 0)

    error();

    else{

    z= x + y;

    }

    为了避免这样的情况,在if和else后面都要加花括号

时间: 2024-08-07 04:32:14

C陷阱与缺陷之语法陷阱的相关文章

C陷阱与缺陷之词法陷阱

该文章及后续文章均为阅读<C陷阱和缺陷>后的读数笔记,方便以后回顾 C陷阱和缺陷电子版图书下载地址:点击打开链接 第一章词法陷阱 1.1 = 不同于 == 在C语言中,符号=作为赋值运算符,符号==作为比较运算符.一般而言,赋值运算相对比较运算出现得更频繁,因此字符数较少的符号=就被赋予更常用的含义--赋值操作.在编写程序的时候,注意不要将赋值操作写完比较相等的操作,也不要将比较操作写为赋值操作. 1.2 & 和 | 不同于 && 和 || 在C语言中,&和|为

[C陷阱和缺陷] 第2章 语法“陷阱”

第2章 语法陷阱 2.1 理解函数声明 当计算机启动时,硬件将调用首地址为0位置的子例程,为了模拟开机时的情形,必须设计出一个C语言,以显示调用该子例程,经过一段时间的思考,得出语句如下: ( (void() () )0 ) (); 像这样的表达式看起来很难理解,但只要将其一层一层地剥离,还是能够理解的.下面我将用几个例子来帮助大家逐渐理解这个表达式. void *a(); void (*b) (); 因为()的优先级高于*,所以*a()为*(a()),a是一个函数,该函数的返回类型为void*

我的《C陷阱与缺陷》读书笔记

第一章 词法"陷阱" 1. =不同于== if(x = y) break; 实际上是将y赋给x,再检查x是否为0. 如果真的是这样预期,那么应该改为: if((x = y) != 0) break; 2. &和| 不同于 && 和 ||   3.词法分析中的"贪心法" 编译器将程序分解成符号的方法是:从左到有一个一个字符的读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符床是否可能是一个符号的组成部分:如

阅读《C陷阱与缺陷》的知识增量

看完<C陷阱与缺陷>,忍不住要重新翻一下,记录一下与自己的惯性思维不符合的地方.记录的是知识的增量,是这几天的流量,而不是存量. 这本书是在ASCI C/C89订制之前写的,有些地方有疏漏. 第一章 词法陷阱 1.3 C语言中解析符号时使用贪心策略,如x+++++y将被解析为x++ ++ +y,并编译出错. 1.5 单引号引起的一个字符代表一个对应的整数,对于采用ASCII字符集的编译器而言,'a'与0141.97含义一致. 练习1.1 嵌套注释(如/*/**/*/)只在某些C编译器中允许,如

C陷阱与缺陷学习笔记

本书的介绍 作者以自己1985年在Bell实验室时发表的一篇论文为基础,结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作.写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过编程过程中的陷阱和障碍. 全书分为8章,分别从词法分析.语法语义.连接.库函数.预处理器.可移植性缺陷等几个方面分析了C编程中可能遇到的问题.最后,作者用一章的篇幅给出了若干具有实用价值的建议. 本书适合有一定经验的C程序员阅读学习,即便你是C编程高手,本书也应该成为你的案头必备书籍. 前言 N年读过这本书

《C陷阱与缺陷》学习笔记(一)

前言和导读 "得心应手的工具在初学时的困难程度往往超过那些容易上手的工具."比较认同这句话.我至今觉得自己其实还是个刚入了门的初学者. 第一章 "词法"陷阱 由于之前学过编译原理,对编译器词法分析(主要是符号识别过程)比较了解,理解起来不困难. 在讲到"="和"=="."|"和"||"."&"和"&&"时,联想起以前见过一些

C陷阱与缺陷 读书笔记

C陷阱与缺陷 1.  typedef用法: ①    定义一种类型别名,而不是简单的宏替换: char *pa,pb;(注意:pb并没有定义为指针,虽然你可能想这么定义它) typedef char* PCHAR PCHAR pa, pb; ②   用在旧的C代码中,帮助struct.以前的代码中,声明struct新对象时,必须带上struct,即形式为:struc结构名对象名,如: struct tagPOINT1 { Int x; Int y; }; struct tagPOINT1 p1;

C陷阱与缺陷 —— 读书笔记-1、词法“陷阱”

<C陷阱与缺陷>是由Andrew Koenig所著,高巍译.Andrew Koenig是AT&T大规模程序研发部(前贝尔实验室)成员,不仅有着多年的C++开发,研究和教学经验,而且还亲身参与了C++的演化和变革,对C++的变化和发展起到重要的影响. 第一章    词法陷阱 编译器中负责将程序分解为一个一个符号的部分,一般称为"语法分析器". 1.1    = 不同于 == while (c='' || c==' ' || c==' ') c=getc(f); 这个循

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

第七章 1.null指针并不指向任何对象,所以只用于赋值和比较运算,其他使用目的都是非法的. 误用null指针的后果是未定义的,根据编译器各异. 有的编译器对内存位置0只读,有的可读写. 书中给出了一种判断编译器如何处理内存0的代码: 1 #include <stdio.h> 2 int main() 3 { 4 5 char *p; 6 p=NULL; 7 printf("location 0 contains: %d\n", *p); 8 9 return 0; 10