C陷阱与缺陷(三)
第三章 语义陷阱
3.1 指针与数组
C语言中只有一维数组,而且数组的大小必须字编译期就作为一个常数确定下来。数组中的元素可以是另外一个数组。
任何一个数组下标运算都等同于一个对应的指针运算。
int a[3];
除了a被用作运算符sizeof的参数这一情形,在其它所有情形中数组名a都代表指向数组a中下标为0的元素的指针,sizeof(a)是整个数组a的大小。
*a是数组a中下标为0的元素的引用,*(a+1)是数组中下标为1的元素的引用。
3.2 非数组的指针
在C语言中,字符串常量代表了一块包括字符串中所有字符以及一个空字符的内存区域的地址。
假设我们有两个这样的字符串s和t,我们希望可以借助常用的库函数strcpy和strcat。
char *r;
strcpy(r,s);
strcat(r,t);
这段函数的问题在于没有初始化r。
char r[100];
strcpy(r,s);
strcat(r,t);
但是这段函数又不能确保r足够大。
char *r;
r=malloc(strlen(s)+strlen(t));
strcpy(r,s);
strcat(r,t);
这段函数问题在于
一、malloc函数有可能无法提供请求的内存。
二、给r分配内存后应该释放。
三、未计算空字符的空间。
char *r;
r=malloc(strlen(s)+strlen(t)+1);
if(!r)
exit(1);
strcpy(r,s);
strcat(r,t);
free(r);
3.3 作为参数的数组声明
int strlen(char s[])与int strlen(char *s)一样
char hello[]="hello";
printf("%s\n",hello)与printf("%s\n",&hello[0])一样
3.4 避免举隅法
举隅:即以含义更宽泛的词语来代替含义相对较窄的词语,或者相反。
char *p="xyz",*q;
P的值是一个指向'x','y','z'和‘\0’4个字符组成的数组的起始元素的指针,
q=p;
P和q现在是两个指向内存中同一地址的指针,这个赋值语句并没有同时复制内存中的字符。两者中一个改变内容,另外一个也随之改变。
3.5 空指针并非空字符串
编译器保证由0转换而来的指针并不等于任何有效的指针。
出于文档化的考虑,常数0这个值经常用一个符号来代替。
#define NULL 0
当常数0被转换为指针使用时,这个指针绝对不能解除引用,即不能企图使用该指针所指向的内容中存储的内容。
(char *)0;
3.6 边界计算与不对称边界
C语言中一个拥有n个元素的数组,它的元素的下标范围是从0到n-1为止。
数组中实际不存在的“溢界”元素的地址位于数组所占内存之后,这个地址可以用于进行赋值和比较。当然如果引用该元素,那就是非法了。
3.7 求值顺序
C语言中只有四个运算符(&&、||、?、,)存在规定的求值顺序。
运算符&&和||首先对左侧操作数求值,只有在需要时才对右侧操作数求值。
逗号运算符,首先对左侧操作数求值,然后该值被"丢弃",再对右侧操作数求值。
注:分隔函数参数的逗号并非逗号运算符。
f(x,y)中的求值顺序是未定义的,而在函数g((x,y))中却是确定的。函数g中只有一个参数,先对x求值再丢弃x,接着求y的值。
3.8 运算符&&、||和!
误用移位符代替逻辑符可能产生结果相同的程序,但这只是巧合。
&和&&的求值顺序不一样。
3.9 整数溢出
C语言中存在有符号和无符号运算两类整数算术运算。
在无符号算术运算中,没有所谓的"溢出"一说。
如果是有符号和无符号数进行运算,那么有符号整数会被转换为无符号整数,"溢出"也不可能发生。
只有当爽法都是有符号整数时,可能发生溢出。解决方法可以是把双方都转换为无符号整数,(unsigned)a。
3.10 为函数main提供返回值
如果函数main并为显示声明返回类型,那默认为整型。
严格情况下我们需要在函数结束添加return 0;或者 exit(0);
C陷阱与缺陷(三)的更多相关文章
- 阅读《C陷阱与缺陷》的知识增量
版权声明:本文为Focustc原创文章.转载请注明作者及出处. https://blog.csdn.net/caozhankui/article/details/35925939 看完<C陷阱与 ...
- 读书笔记--C陷阱与缺陷(一)
要参与C语言项目,于是作者只好重拾C语言(之前都是C++,还是C++方便). 看到大家都推荐看看 C陷阱与缺陷(C traps and pitfalls),于是好奇的开始了这本书的读书之旅. 决定将 ...
- C陷阱和缺陷学习笔记
这段时间把<C陷阱和缺陷>看了,没时间自己写总结.就转一下别人的学习笔记吧http://bbs.chinaunix.net/thread-749888-1-1.html Chapter 1 ...
- 读书笔记--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中数组注意的两点: 1) C语言只有一维数组,但是数组元素可以是任何类型对象,是另外一个数组时就产生了二维数组.数组大小是常数(但GCC实现了变长数组..) ...
- c缺陷与陷阱笔记-第三章 语义陷阱
1.关于数组和数组指针 数组的名字默认是常量指针,值不能改变的,例如 int a[]={1,2,3,...},这个a的类型时int *,所以如果有int *p,那么a=p是合法的,其他的指针类型,例如 ...
- 程序员必知的Python陷阱与缺陷列表
本文关注的主要是python陷阱,具体而言,是指CPython,而且除非特别说明,所有代码示例都是在python2.7运行的. 我个人对陷阱的定义是这样的:代码看起来可以工作,但不是以你“想当然“”的 ...
随机推荐
- 脑波设备mindwaveTGC接口示例
TGC是一个后台应用程序,它负责和脑波设备建立连接,并获取数据,另一方面,它打开了一个端口在监听,让二次开发的应用程序,可以通过socket连接到这个TGC后台程序,获取脑波数据并展示,这种接口适合非 ...
- Uber在华从沸点到冰点 搞定这些才能继续走下去
腾讯科技 蒋栩根 5月6日报道 五一前夕,本应坐等笑看小长假带来的喜人业绩的Uber被广州市工商.交委.公安部门的联合检查当头浇了一盆冷水,也被戴上了一顶“涉嫌非法运营”的帽子.而一天前,它才与广物汽 ...
- addEventlistener监听的事件完成一次后自动取消与jquery的one方法比较;animate动画制作,arguments.callee的用法
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- nyist 202 红黑树(二叉树中序遍历)
旋转对中序遍历没有影响,直接中序输出即可. #include <iostream> #include <cstdio> using namespace std; int n; ...
- Boost源代码学习---shared_ptr.hpp
最近观看Boost库源代码.Boost功能强大的库,但它的许多源代码,十一细读太费时间,毕竟,还有其他东西要学.所以我决定脱脂感兴趣的章节,他们的设计思路和难以理解的地方记录. shared_ptr是 ...
- nginx 使用安装问题及解决方案
如何安装清参考:http://www.runoob.com/linux/nginx-install-setup.html 可以先不用配置,等理解后在配置. 在启动nginx时,出现提示: nginx: ...
- ASP.NET Web编程
runat="server"直接回交服务器,处理数据,又以数据加密后的hidden属性的input控件插入回去,实现表单的状态保存 ruant="server" ...
- java中如何计算两个时间段的月份差
直接计算,先取得两个日期的年份和月份,月份差=(第二年份-第一年份)*12 + 第二月份-第一月份
- JBoss 系列二十一:JBossCache核心API
内容简介 本处介绍JBossCache相关的主要API,我们目的通过本部分描述,读者可以使用JBossCache API,在自己的应用中使用JBossCache. Cache接口 Cache 接口是和 ...
- 在raw_input()中使用中文提示,在CMD下中文乱码问题解决。。。
错误的程序及结果: 解决1: guess = int(raw_input('请输入一个整数:'.decode('utf-8').encode('gbk'))) 解决2: guess = int(raw ...