C陷阱和缺陷学习笔记

C小陷阱 (1) 大家首先来看下面这么一段代码。   #include #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) int array[] = {23,34,12,17,204,99,16}; int main() { int d; for(d=-1;d <= (TOTAL_ELEMENT 阅读详情
 
C陷阱和缺陷学习笔记:
 
词法陷阱:
1        = 不同于==不要在程序中将两者写错,小心。将表达式与常量比较时,可将常量放在左边。
2        &| 不同于&& ||
3        词法分析中的贪心法:每个符号应该包含尽可能多的字符。如果(编译器的)输入流截至某个字符前都已经分解为一个个符号,那么下一个符号将包括从该字符之后可能组成一个字符的最长字符串。如y = x/*p,那么/*将作为一个符号对待.
4        如果一个整形变量第一个字符是0,那么该常量被视为8进制数。
5        Char c = ‘cxf’。在vcGcc中,依次用后一个字符覆盖前一个字符,最后得到的整数值是最后一个字符的整数值。
 
语法陷阱:
1        c变量声明由类型和一组类似表达式的声明符组成。声明符与表达式类似,对他求值返回一个声明中给定类型的结果。如float f, ((f))。知道了如何声明一个变量,那么该类型的类型转换符就很容易得到了:将声明中的变量名和分号去掉,再将剩余的部分用个括号“封装”起来即可。如float(*h) (),则float(*)()就是“指向返回值是浮点类型的函数的指针“的类型转换符。(*void*)())0)()调用地址为0位置的的例程。
2        运算符优先级:单目运算符,算术运算符,移位,关系,逻辑,条件, 赋值
3        switch语句中case中,不要忘记break,若刻意要省略,请加注释
4        C语言中只有一维数组,而且数组的大小必须在编译期间就作为一个常数确定下来。多维数组是通过一维数组仿真的,因为数组的元素可以是任何对象,当然也可以是数组。   
对数组,我们只能做两件事,确定其大小,以及获得指向该数组下标为0的元素的指针。其它的有关数组的操作,实际上是通过指针进行的。
 
语义陷阱:
1          空指针并不等于空字符串。编译器保证由0转换而来的指针不等于任何有效的指针。当将0赋值非一个指针变量时,绝对不能企图使用该指针指向的内存中存储的内容。
2          在使用范围时,使用不对称边界方式。第一个是“入界点”(序列中第一个被占用的元素),第二个是“出界点”(序列中第一个被释放的元算)。For(int I = 0 ; I < 10; i++)。尽量不要使用For(int I = 0 ; I <9; i++)
3          数组的下标如果用入界口加出界口来表达(即10个元素,其下标为0 <= n < 10 ),则元素个数即为上界与下界之差,即下界。若为空,则上界等于下界。任何情况下上界也永远不可能小于下界。
    尽量采用非对称边界法。
     一个有N个元素的数组 ,我们可以使用a[N]进行比较和赋值,但不能引用其内容。
4          C语言中只有4个运算符存在规定的求值顺序&&| | ?:和,。其他的运算符对器操作数求值的顺序是未定义的。特别的是,赋值运算符并不保证任何求值顺序。Y[i]=X[i++] 错误。
5          记得为main提供返回值.
 
连接:
1          为避免命名冲突,请对变量或函数使用static修饰符.为了定义与库函数中同名的函数,可将文件中要定义的函数加static修饰.
2          使用外部函数前,一定要声明.否则,没有声明,函数返回值将默认为整型.
3          外部声明要与定义类型一致.不能声明是extern int n,而定义是long n.
4          同一个外部变量在不同的地方被声明为不同的类型,这种错误大部分编译器是检不出来的。
 
  char file[]= "/etc/password";
   

    extern char* file;

是不一样的。
 
库函数:
1          注意getchar()返回整型,不是字符型.
2          为了保持与过去不能同时进行读写操作的程序的向下兼容性,一个输入操作不能随后直接紧跟一个输出操作,反之依然,如果要同时进行输入和输出操作,必须在其中插入fseek函数的调用.:
  FILE *fp;
     struct record rec;
       while (fread((char *)&rec, sizeof(rec),1,fp) = 1)
           {   
     if(/* */)
                {
          fseek(fp, -(long)sizeof(rec), 1);
          fwrite((char *)&rec, sizeof(rec), 1,fp);
          fseek(fp, 0l,1);
         }
}
3         缓冲输出和内存分配:
可通过setbuf函数控制程序的缓冲输出.
#include <stdio.h>
void main(void)
{
     int c;
     char buf[BUFSIZ];
     setbuf(stdout,buf);
     
     while((c = getchar()) != EOF)
          putchar(c);
}
这个是不对的。buf最后一次被清空是在什么时候?答案是在main函数结束之后,作为程序交回控制给操作系统之前C运行时库所必须进行的清理工作的一部分。但是在此之前buf已经被释放。
解决方法一是加上static 声明。也可以把buf声明完全移到main函数之外。第二种办法是动态分配缓冲区,在程序中并不主动释放分配的缓冲区
4         不能直接使用errno检测错误,应先检测作为错误指示的返回值,确定程序已经执行失败.然后,再检查errno,搞清原因.
   /* 调用库函数 */
     if(
返回的错误值)
        
检查errno
5         库函数signal
从理论上说,一个信号可能在C程序执行期间的任何时刻上发生,甚至可能出现在某些复杂的库函数(如malloc)的执行过程中。因此从安全的角度讲,信号的处理函数不应该调用上述类型的库函数。基于同样的原因,从signal处理函数中使用longjump退出,通常情况下也是不安全的:因为信号可能发生在malloc 或者其它库函数开始更新某个数据结构,却又没有最后完成的过程中。因此signal处理函数能够做的安全的事情,似乎就只有设置一个标志然后返回,期待以后主程序能够检查到这个标志,发现一个信号已经发生。 
然而,就算这样做也并不总是安全的。当一个算术运算错误引发一个信号时,某些机器在signal处理函数返回后还将重新执行失败的操作。因此对于算术运算错误,signal处理函数的惟一安全、可移植的操作就是打印一条出错消息,然后使用longjumpexit立即退出程序。
     
当一个程序异常终止时,程序输出的最后几行常常会丢失,原因是缓冲。
 
预处理器:
1         不要忽视宏中的括号.
2         宏不是函数.将宏中的参数都加上括号,将整个结果表达式也括起来.防止副作用.
3         宏不是语句:#define assert(e) ((void)((e)||_assert_error(_FILE_,_LINE_)))
4         宏不是类型定义;不要用#define定义类型,而是用typedef定义新类型.
 
可移植性:
1   因为字符串常量可以用来表示一个字符数组,所以在数组名出现的地方都可以用字符串常量末端替换     如:    "0123456789"[n%10]
2  注意C标准的变化,新特性的使用.
3   c标准所能保证的只是,c实现必须能够区别出前6个字符不同的外部名称,且并没有要求区分大小写。避免诸如:print_char(),print_int()
4  整数长度的相对长度规定:short类型的值肯定能被int型容纳,int型肯定能被long型整数容纳;一个普通(int类型)整数足够大以容纳任何数组下标;字符长度由硬件特性决定.
5   随机数最大值:RAND_MAX
 
 
《C陷阱缺陷学习笔记 第一章 词法陷阱 笔记本:《C陷阱缺陷》 创建时间:2018/4/23 22:06:21 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs 阅读详情

相关推荐

《C陷阱缺陷学习笔记总结:词法陷阱、语法陷阱、语义陷阱,连接、库函数、预处理器、可移植性缺陷及其他

近期课程的作业需要用到RPC编程,除了课堂上学到的知识,还得亲自动手。打算先写个简单的HelloWorld练习一下,顺便复习一下学到的知识。   RPC意为远程过程调用协议(Remote Procedure Call Protocol)。编制好单机应用程序,然后划分为两个或多个程序片,加入通信协议使得每片可以在单独的计算机上运行。从一个程序片调用另一个程序片的过程称为远程过程调用,即RPC。

benpaobagzb的博客 579

《C陷阱缺陷》2.1:理解函数声明 ( *( void( * )( ) )0 )( ) 学习笔记

---------------------------------------------------------------------------------------------------------------------------------《C陷阱缺陷》----第二章 语法陷阱_if (((t = btype(pt1->aty) == strty) || t == uniont-CSDN博客

huangdou666的博客 418

《C陷阱缺陷学习笔记(上):词法陷阱、语法陷阱、语义陷阱

自从上大学起,接触C也很久了,但是一直不怎么深入,也疏于练习。课程学习之余,专门的C只看过《C程序设计语言》、《C primer plus》,现在终于有了点时间看看更多的书了。本文主要记录阅读学习《C陷阱缺陷》的一些心得体会。 11月15日 前言导读   “得心应手的工具在初学时的困难程度往往超过那些容易上手的工具。”比较认同这句话。我至今觉...

weixin_34310127的博客 146

C陷阱缺陷学习笔记

N年读过这本书,当时读的时候囫囵吞枣,加上时间久远,90%的内容都忘记了。昨天在整理书籍的时候翻出来了,这本书短小精悍却不失为经典之作。抽出时间再拜读一遍,顺便做做笔记,记录精华。

zfs2008zfs的博客 3601

学习笔记】C缺陷陷阱

优先级比单目运算符要低的,接下来就是双目运算符,在双目运算符中,算术运算符的优先级最高,移位运算符次之,关系运算符再次之,接着是逻辑运算符,赋值运算符,最后是条件运算符;在所有的运算符中,逗号运算符的优先级最低;典型的链接器把编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体,该实体能够被操作系统直接执行,其中某些目标模块是直接作为输入提供给链接器的;答:一个异常终止的程序可能没有机会来清空其输出缓冲区,因此,该程序生成的输出可能位于内存的某个位置,但却永远不会被写出了,

365

【转】C缺陷陷阱学习笔记

http://www.cnblogs.com/hbiner/p/3591335.html?utm_source=tuicool&utm_medium=referral 这段时间把《C陷阱缺陷》看了,没时间自己写总结。就转一下别人的学习笔记吧http://bbs.chinaunix.net/thread-749888-1-1.html ...

weixin_30685029的博客 126

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

《C陷阱缺陷学习笔记(一) 分类: c++专区 2014-06-06 16:12 308人阅读 评论(0) 收藏 举报 前言导读   “得心应手的工具在初学时的困难程度往往超过那些容易上手的工具。”比较认同这句话。我至今觉得自己其实还是个刚入了门的初学者。   第一章  “词法”陷阱     由于之前学过编译原理,对编译器词法分

xu_ya_fei的专栏 490

c陷阱缺陷学习笔记

1.1 = 赋值运算符 == 比较运算符 1.2 && 逻辑或 ||逻辑与 & 按位或 | 按位与 1.3 如果(编译器)输入流截止至某个字符之前都已经被分解为一个个符号,那么下一个符号将包括从该字符之后可能组成一个符号的...

diaxfw2168的博客 150

c陷阱缺陷学习笔记

http://c.chinaitlab.com/c/basic/200907/789321.html   词法陷阱:    1        = 不同于==不要在程序中将两者写错,小心。将表达式与常量比较时,可将常量放在左边。    2        &| 不同于&& ||.    3        词法分析中的贪心法:每个符号应该包含尽可能多的字符。如果(编译器的)

james@BJ的专栏 582

C陷阱缺陷学习笔记

前言 掌握细节并不难,难的是如何运用之妙! 词法“陷阱” 词:单词 符号=作为赋值预算,是因为操作频繁,书写简单 词法分析中的“贪心法” a—b与表达式a – - b的含义相同,而与a - – b的含义不同 y = x/*p与y = x / *p不同(第一个/*被理解为注释符) 理解:这也许就是编码规范要求操作符两侧添加合理空格的原因之一吧 字符与字符串 用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针。 字符’/0’对应的十进制是0 语法“陷阱” 运算符优先级 括号(),数组下标[]

canpool 531

C缺陷陷阱学习笔记

 易上手的工具往往功能有限,满足不了高手。得心应手的工具初学时的困难往往超过那些容易上手的工具。但一旦熟练后,则会觉得那些易上手的工具最后都碍手碍脚。 使其难于做傻事往往使其难于做聪明事。 Chapter 1 词法陷阱 程序中的单个字符孤立起来看并没有什么意义,只有结合上下文才有意义,如p->s = "

trunk0813的专栏 419
上一篇: 如何用正确的方法来写出质量好的软件的75条体会
下一篇: 二叉树实现(包括遍历等各种操作,递归与非递归)
adcxf
博客等级 码龄20年 163粉丝 111原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值