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陷阱与缺陷(二)的更多相关文章
- C陷阱和缺陷学习笔记
这段时间把<C陷阱和缺陷>看了,没时间自己写总结.就转一下别人的学习笔记吧http://bbs.chinaunix.net/thread-749888-1-1.html Chapter 1 ...
- 阅读《C陷阱与缺陷》的知识增量
版权声明:本文为Focustc原创文章.转载请注明作者及出处. https://blog.csdn.net/caozhankui/article/details/35925939 看完<C陷阱与 ...
- 读书笔记--C陷阱与缺陷(一)
要参与C语言项目,于是作者只好重拾C语言(之前都是C++,还是C++方便). 看到大家都推荐看看 C陷阱与缺陷(C traps and pitfalls),于是好奇的开始了这本书的读书之旅. 决定将 ...
- 读书笔记--C陷阱与缺陷(七)
第七章 1.null指针并不指向任何对象,所以只用于赋值和比较运算,其他使用目的都是非法的. 误用null指针的后果是未定义的,根据编译器各异. 有的编译器对内存位置0只读,有的可读写. 书中给出了一 ...
- [C陷阱和缺陷] 第1章 词法“陷阱”
有感自己的C语言在有些地方存在误区,所以重新仔细把"C陷阱和缺陷"翻出来看看,并写下这篇博客,用于读书总结以及日后方便自身复习. 第1章 词法"陷阱" 1.1 ...
- C语言学习书籍推荐《C陷阱与缺陷》下载
下载地址:点我 凯尼格 (作者), 高巍 (译者) <C和C++经典著作:C陷阱与缺陷>适合有一定经验的C程序员阅读学习,即便你是C编程高手,<C和C++经典著作:C陷阱与缺陷> ...
- 《C陷阱与缺陷》整理二
1.数组名作实參 在C语言中,我们没有办法将一个数组作为函数參数传递,假设我们使用数组名作为參数.这个时候数组名立马会被转换为指向该数组的第一个元素的指针. 关于这一点的理解能够向前深 ...
- 读书笔记--C陷阱与缺陷(二)
第二章 1. 理解函数声明 书中分析了复杂的类型声明方式,也说明了使用typedef声明会更好理解,推荐大家使用typedef进行函数声明. 书中类型分析一层一层挖掘,让读者可以理解多层嵌套的类型含义 ...
- 程序员必知的Python陷阱与缺陷列表
本文关注的主要是python陷阱,具体而言,是指CPython,而且除非特别说明,所有代码示例都是在python2.7运行的. 我个人对陷阱的定义是这样的:代码看起来可以工作,但不是以你“想当然“”的 ...
随机推荐
- BingMap的GeocodeService进行地理位置正向和反向检索--后台实现
一.加入GeocodeService的Web服务引用 地理编码服务(GeocodeService)是以WCF技术公布的一个Web服务,地图编码服务提供了以一个有效的物理地址在地图上匹配其相应的地图地址 ...
- Selenium之偷懒教程
进来一直停留在基础理论知识的学习中,认为太乏味,就写了一个网页自己主动化的demo:自己主动写日报.省的以后自己打开网页写啦. 直接上代码: 自己主动填写日报DEMO import java.io.B ...
- ios 设备用jquery live绑定 click 事件不管用
问题描述:用js拼接的html追加到页面,然后用 live 绑定click事件不起作用 解决办法:1.直接在标签写onclick事件 2.给需要绑定的标签添加css样式{cursor:pointe ...
- [Jobdu] 题目1385:重建二叉树
根据一棵二叉树的先序遍历和后序遍历,重建二叉树 例子: 我们先来看一个例子,二叉树如上图,则先序遍历为:1 2 4 7 3 5 6 8,中序遍历为:4 7 2 1 5 3 8 6 思路: 先序遍历中的 ...
- subversion和客户端的应用
1.安装svn的服务器端subversion.以及windows客户端TortoiseSVN: 2 cmd 建立库,名字为svnpro ----- svnadmin create F:\svnpro, ...
- servlet三种实现方式之三通过继承HttpServlet开发servlet
servlet有三种实现方式: 1.实现servlet接口 2.继承GenericServlet 3.通过继承HttpServlet开发servlet 第三种: import java.io.*; i ...
- android--email发送邮件,文本还有附件形式的邮件
1.首先用的jar包为javaemail 下载地址: https://yunpan.cn/cB3kY8WIvcGtU (提取码:e042) 2.工具包 package com.kllayhello.u ...
- c# zip file and folder programmatically
In .net 4.5 Framework, we can zip a file by this way: private static string CompressFile(string sour ...
- CSS3 模拟笑脸
参考 http://www.html5tricks.com/demo/html5-css3-smile-face/index.html 它还做了舌头... 一开始我都是用JS实现的动画 当然了 眼 ...
- 射频识别技术漫谈(22)——RC系列射频芯片的寄存器操作
前面提到,RC系列内部64个寄存器的正确操作是软件编写的关键.正确设置寄存器首先要做到与寄存器正确通信,其次是要对寄存器写入正确的值. RC系列射频芯片与微控制器的接口有并口和SPI接口两种类型.显然 ...