原标题:C语言陷阱一

1、

while ( c= ' ' || c== 't' || c== 'n')

c=getc(f);

程序员有时候会将=写成==,因为赋值运算符=的优先级要低于逻辑运算符||,因此实际上上述表达式是把 **’ ’ || c== ‘t’ || c== ‘n’**的值赋值给c,因为’ '不等于0(ASCII码值为32),所以无论变量c为何值,上述表达式的结果都是1,因此循环将一直下去知道文件结束。

2、

if((filedesc == open (argv[i], 0))<0)

error;

这类错误是把赋值运算符误写成比较运算符的类型,open函数若执行成功,则返回0或正数,若open函数执行失败,将返回-1。因为比较运算符==的结果只能是0或1,所以函数error将没有机会被调用。若代码执行,似乎一切正常,除了变量filedsec的值不再是open函数的返回值,在某些编译器在遇到这种情况下,会警告与0比较无效。

3、整型常量

如果一个整型常量的第一个数字是0,那么该常量将被视为八进制数。因此10与010的含义截然不同。

有时候在上下文中为了格式对齐的需要,可能无意中将十进制数写成了八进制,例如:

struct

{

int part_number;

char *deion;

}parttab[]=

{

046,"left-handed widget",

047,"right-handed widget",

125,"frammis"

};

4、理解函数声明

(*(void(*))0);

如上所示的语句,一般很难看懂,可以利用下面方法来解析:构造这类表达式其实只有一条简单的规则:按照使用的方式来声明。

任何C语言变量的声明都是由两部分组成:类型以及一组类似表达式的声明符。声明符从表面上看与表达式有些类似,对它求值应该返回一个声明中给定类型的结果。简单的声明符为单个变量:

float f,g;

因为声明符与表达式相似,可以在声明符中任意使用括号:

float ((f));

同样的逻辑也适用于函数和指针类型的声明:

float ff;

这个声明的含义,表达式ff求值的结果是一个浮点数,ff是一个返回值为浮点类型的函数。

float *pf;

类似的,这个声明的含义表示*pf是一个浮点数,也就是说,pf是一个指向浮点数的指针。

以上这些形式在声明中可以组合起来。

float *g,(*h);

上式表明*g与(*h)是浮点表达式。*g中g是一个,该函数的返回值类型为指向浮点数的指针。(*h)中h是一个函数指针,h所指向的函数的返回值为浮点类型。

在了解如何声明一个给定类型的变量,那么该类型的类型转换符就很容易得到:只需要把声明中的变量名和声明末尾的分好去掉,再将剩余的部分用一个括号整个“封装”起来即可:例如

float (*h);

表示h是一个指针函数,h是一个指向返回值为float类型的函数的指针,h所指向的函数的返回值是float类型。

(float (*));

表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。

现在,开始利用两步分析 (*(void(*))0);

step1:假定变量fp是一个函数指针,则调用fp所指向的函数方法如下:

(*fp);

因为fp是一个函数指针,故*fp就是该指针所指向的函数,所以(*fp)就是调用该函数的方式。ANSIC标准允许程序员将上式简写为fp,但是要记住这种写法只是一个简写形式。

step2:找到一个恰当的表达式来替换fp,最简单的转换如下:

(*0);

但是,上式并不能生效,因为运算符*必须要一个指针来做操作数,这个指针应该是一个函数指针,这样经运算符作用后的结果才能够作为函数被调用。因此,必须对上式中的0作类型转换,转换后的类型可以大致描述为:指向返回值为void类型的函数的指针。

若fp是指向返回值为void类型的函数的指针,那么(*fp)的值为void,fp的声明如下:

void (*fp);

因此,可以用下式来完成调用存储位置为0的子例程:

void (*fp);

(*fp);

下面对一个常数进行类型转换,将其转换为该变量的类型:只需要在变量声明中将变量名去掉即可。因此,将常数0转换为“指向返回值为void的函数的指针”类型:

(void (*))0;

因此,可以用(void (*))0;来替换fp:

(*(void (*))0);

注:利用typedef能够使表示更加清晰:

typedef void (*funcptr);

(*(funcptr)0);

5、运算符优先级

while (c=getc(in) != EOF)

putc(c,out);

因为关系运算符的优先级要高于赋值运算符,所以上式c的实际值是函数getc(in)的返回值与EOF比较的结果。因此,最后得到的文件中只是包括了一组二进制值为1的字节流。

正确写法:

while ((c=getc(in)) != EOF)

putc(c,out);

6、函数调用

如果函数f是一个函数:

f;

是一个函数调用语句;

f;

是一个什么都不做的语句,更准确的说,这个语句是计算f的地址,却并没有调用f函数。

7、指针与数组

c语言中的数组注意的地方有一下两点:

(1)c语言中数组只有一维数组,而且数组大小必须在编译期间就作为一个常数确定下来。然而数组中的元素可以是任何类型的对象,当然可以是另外一个数组。这样就可以很容的形成一个多维数组。

(2)对于一个数组,只有两个操作:确定该数组的大小,以及获得指向该数组下标为0的元素指针。其他有关数组的操作,即使看上去是以数组下标进行运算的,实际上都是通过指针进行的。

int array[12][31];

这个语句声明了array是一个数组,该数组拥有12个数组类型的元素,每个元素是一个拥有31个整型元素的数组。

sizeof(array)=31*12=372;

如果array不是用于sizeof的操作数,而是用于其他场合。那么array总是被转换成一个指向array数组的起始元素的指针。

array[4]表示一个有着31个整形元素的数组。

sizeof(array[4])=31*sizeof(int)=31*4=124;

指针p指向了数组array[4]中下标为0的元素:

int *p;

p=array[4];

整型i得到数组array某个位置的值:

int i;

i=array[4][7];

i=*(array[4]+7);

i=*(*(array+4)+7);

下式是错误的:因为array是一个二维数组,即数组的数组,在此处array会将其转换成一个指向数组的指针;而p是一个指向整型变量的指针,将一种类型的指针赋值到另一种类型的指针是非法的。

p=array;

若要声明一种指向数组的指针的方法,如下:

int (*ap)[31];

上述语句声明了*ap是一个拥有31个整型元素的数组,ap就是一个指向这样数组的指针。因此:

int array[12][31];

int (*parray)[31];

parray=array;

这样,parray将指向array的第一个元素。

8、指针大小

char *pc;

sizeof(pc);

在32位机器中是4字节;

在64位机器中是8字节;

9、if(3 == i){...}

如此写法可以避免 将关系运算符写成赋值运算符,避免bug;

10、malloc动态申请的内容,释放后,将变量指向地址为空的地方会更加安全

int *pmal=(int *)malloc(100*sizeof(int));

...

...

...

if(pmal)

{

free(pmal);

pmal=NULL;

}

技术源于积累,成功来自执着返回搜狐,查看更多

责任编辑:

在c语言中3ap是不合法的变量,C语言陷阱一相关推荐

  1. java成员变量默认是_在Java语言中,String类型的成员变量的默认初始值是( )

    在Java语言中,String类型的成员变量的默认初始值是( ) 答:C.null 学生最主要的权利是() 答:受教育权 提倡教育要适合孩子的 "敏感期"的教育家是 答:蒙台梭利 ...

  2. c语言中int的取值范围_c语言入门(1)

    c语言入门 C语言一经出现就以其功能丰富.表达能力强.灵活方便.应用面广等特点迅速在全世界普及和推广.C语言不但执行效率高而且可移植性好,可以用来开发应用软件.驱动.操作系统等.C语言也是其它众多高级 ...

  3. c语言中3%3e2%3e1的值,C语言--ch2--数据类型和表达式.ppt

    C语言--ch2--数据类型和表达式 第二章 数据类型和表达式 2.1 数据类型 在C语言中,数据类型可分为:基本数据类型,构造数据类型,指针类型,空类型四大类. 其中基本数据类型可分为: 整型:整数 ...

  4. c语言中eles后面分号的作用,C语言 if else 语句详细讲解

    前面我们看到的代码都是顺序执行的,也就是先执行第一条语句,然后是第二条.第三条--一直到最后一条语句. 但是对于很多情况,顺序结构的代码是远远不够的,比如一个程序限制了只能成年人使用,儿童因为年龄不够 ...

  5. c语言中1%3c%3c2 什么意思,c语言练习题

    篇一:C语言考试题库及答案 C语言理论上机考试选择题部分(共200题,仅针对11级定向专业) 1.下面程序的输出是___D______ #include void main() { int k=11; ...

  6. c语言中5l是数值或字符常量,C语言练习题-选择题(带答案)

    以下为<C语言练习题-选择题(带答案)>的无排版文字预览,完整格式请下载 下载前请仔细阅读文字预览以及下方图片预览.图片预览是什么样的,下载的文档就是什么样的. C语言练习题-选择题(带答 ...

  7. c语言中5l是数值或字符常量,C语言中什么叫做正确的数值或字符常量?

    用一对单引号将一个字符括起表示合法的字符常量.例如'a'.数值包括整型.浮点型.整型可用十进制,八进制,十六进制.八进制前面要加0,后面由0到7八个数表示. 在C语言中,字符常量有以下特点: 字符常量 ...

  8. c语言中point的用法_关于C语言Switch语句,先学这些技巧够不够?

    一.C语言中switch的用法 1.switch后面括弧内的[表达式],ANSI标准允许它为任何类型: 2.当表达式的值与某一个case后面的常量表达式的值相等时,就执行此case后面的语句,否则,就 ...

  9. c语言箭头指针的作用,C语言中,结构体成员变量的点和箭头

    C语言中,调用成员变量用点还是用箭头,取决于当前的ID是指针还是结构体本身. 如:typedef struct { float height; float weight; } Person; int  ...

最新文章

  1. delphi 回调函数
  2. python for-Python for循环及基础用法详解
  3. SAP物料标准成本估算结果
  4. Go gin获取GET请求参数
  5. 代码小结:时区的时间问题
  6. wenstorm设置谷歌_WebStorm+Chrome调试Vue步骤
  7. 吉林大学不如温州大学,泰晤士最新世界大学排名引发争议
  8. pythonmatplotlib刷新_matplotlib:如何刷新figure.canvas
  9. 7-2 简单计算器 (13 分)
  10. mysql bit 设置默认值_为什么数据库字段需要设置默认值
  11. String的intern()详解
  12. python 贝塞尔曲线对图像进行扭曲_Python3 OpenCV3图像处理-图像扭曲
  13. 注册德国商标的详细介绍
  14. 今年这情况。。咱还是留个心眼吧
  15. windows 驱动开发基础(二)事件通知---关于irp处理,DPC,链表等
  16. 阿里内部发布最新版Java进阶笔记,金九银十看这份文档就够了
  17. CISAW证书发证机构是哪里?权威性如何?
  18. pytorch 深度学习补充
  19. java判断数据库是否存在_java判断数据库是否存在的方法
  20. 工具推荐:4个小众Chrome插件,最后一个互联网人必备!

热门文章

  1. 【排序算法】交换排序(C++实现)
  2. igxe本地机器人怎么用_三分钟快速了解如何使用机器人系统
  3. html css 科技感异形边框,CSS边框外的小三角形+阴影效果的实现。
  4. MCV 的几种表单提交方式
  5. 【语言的灵魂】C语言的灵魂 “ 指针 ”
  6. 深度学习在计算机视觉领域(图像,视频,3D点云,深度图等)应用全览
  7. 网站不写SEO文案? SEO就算了吧!
  8. JAVA toString方法详解
  9. html中精灵图片路径,css中精灵图是什么意思?
  10. java图片批量添加_java实现邮件中插入批量图片