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运行的. 我个人对陷阱的定义是这样的:代码看起来可以工作,但不是以你“想当然“”的 ...
随机推荐
- o怎么样racle输入dmp数据库文件
Oracle进出口数据imp/exp等价物oracle数据恢复和备份. exp命令可以从远程数据库传输数据server出到本地的dmp文件,imp命令能够把dmp文件从本地导入到远处的数据库serve ...
- 我的一个关于RFID的项目总结
去年做的一个项目,今天在这里想总结一下,这是主要流程: [0]RFID(Reader)---->[1]网络---->[2]接收处理程序---->[3]队列---->[4]读/存 ...
- 浅谈Servlet(二)
1.forward(请求的转发)和redirect(重定向) 目的:都是为了把一个Servlet的功能,拆分到多个Servlet中,便于后续代码的维护. a.forward(请求转发) (1).如何在 ...
- 写后台SQL的一些心得
昨天犯了一个错,其实是前几天写的代码犯的错,今天发现的.这是原来的代码: <update id="updateInfoByFoodId"> update food se ...
- Lowest Common Ancestor of a Binary Search Tree (BST)
Given a binary search tree(BST), find the lowest common ancestor of two given nodes in the BST. Node ...
- hive 分区操作记录
创建分区: alter table table_name add partition (dt='20150423') location '/data/text/20150423';
- CSS 文章段落样式
#adiv p { text-align: left; text-indent: 2em; line-height:25px; font-family:微软雅黑; font-size:medium; ...
- Android 开发笔记“Eclipse 调试和快捷键”
原文地址:http://blog.sina.com.cn/s/blog_5cf876340100aswr.html Eclipse 调试器和 Debug 视图 Eclipse SDK 是针对 Java ...
- ubuntu NFS
NFS(Network File System, 网络文件系统)可以通过网络将分享不同主机(不同的OS)的目录——可以通过NFS挂载远程主机的目录, 访问该目录就像访问本地目录一样! 一般而言, 使用 ...
- 名叫Florida的女孩问题
近读列纳德·蒙洛迪诺的<醉汉的脚步>,读到第六章,作者举了一个超级变态的例子来解释条件概率或者说是贝叶斯概率. 1.先来看一个简单点的问题:已知所有有2个孩子的家庭,其中一个家庭2个孩子都 ...