#define+do{} while(0)+peeror的思考_电气自动化网
首页 资讯 应用 高压 设计 行业 低压 电路图 关于

单片机

旗下栏目: PLC 嵌入式 单片机 DCS

#define+do{} while(0)+peeror的思考

单片机 | 发布时间:2018-05-31 | 人气: | #评论# | 本文关键字:C,C语言,#define,do{} while(0),pe
摘要:今天看到这样一个程序,还挺有意思,感觉里面知识点挺多的,就想着复习复习! #defineERR_EXIT(m)do{perror(m);exit(EXIT_FAILURE);}while(0) 1. perror函数 2. exit函数以及EXIT_TAIURE 3. #define 与do{}while()函数的

今天看到这样一个程序,还挺有意思,感觉里面知识点挺多的,就想着复习复习!#define ERR_EXIT(m)   do  {   perror(m);   exit(EXIT_FAILURE);}  while(0)   

1.    perror函数

2.    exit函数以及EXIT_TAIURE

3.    #define 与do{}while()函数的特殊结合

关于perror函数:

头文件:       #include     <stdio.h>(不可以掉了这个文件,因为perror就是在这个文件中)和   #include <stdlib.h>

定义函数

void perror(const char *s);

函数说明

perror( ) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno 的值来决定要输出的字符串。

在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

范例

#include <stdio.h>
      #include <errno.h>

int main(void)

{

FILE *fp ;

fp = fopen( "/root/noexitfile", "r+" );

if ( NULL == fp )

{

perror("/root/noexitfile");

}

return 0;

}

运行结果

[[email protected] io]# gcc perror.c

[[email protected] io]# ./a.out

/root/noexitfile: No such file or director

关于exit和EXIT_TAIURE

我们在main函数中通常用:return 0;来结束程序,返回一个值,但是这些仅仅是局限于非void的情况下,也就是   void  main()中。但是如果把exit函数用在main函数中,不管main函数的返回值是不是void,exit都是有效,在(int  main()的情况下,返回值等同于return)

 exit用在子程序中,终结程序,跳回操作系统

只用exit(0)代表程序的正常退出,其余的参数皆表示程序的异常退出

如果main()在一个递归程序中,exit()仍然会终止程序;但return将

控制权移交给递归的前一级,直到最初的那一级,此时return才会终止程序。return和exit()的另一个区别在于,即使在除main()之外的函数中调用exit(),它也将终止程序。

然而对于:EXIT_FALURE(在vc6.0中,它被定义于头文件stdio.h中)

#define  EXIT_FALURE   0

#define  EXIT_SUCESS  1

关于宏中使用do-while函数

一般我们都知道do-while函数基本上都用于循环中,但是在这里为什么要加入do while 0呢,不是也是执行一次吗,放在这里它有什么优势吗???我们知道define函数的简单用法是:定义一个常量,或者一个简单地语句,或者函数,都只是简单地往后面加一个分号(“;”),但是究竟多个顺序执行的语句如何跟define联系起来呢?它们又跟do-while有什么关系呢??

在define中定义一个可以执行多个函数的宏

第一种:

  1. #define Sequence     print1();print2();  

然后我们的程序可能这样调用:

  1. Sequence;  

 然后它的确是在预编译期就被这样的替换了:

  1. print1();print2();  

能达到我们的预期效果:但是如果我们的程序是这样的呢?

if(flag)  

  1.         Sequence;  

它就被替换成为了这样(就不是我们预期的那样了):

if(flag)  

  1.         print1();  

  2. printf(2);  

也就是说无论flag这个标志值是真的假的,print2()这个函数都会被执行了,
所以这是我们经常犯的错误,也是大家经常犯得错误了

第二种

  1. #define Sequence    {print1();print2();}  

可以看到跟第一种的区别仅仅是,将两个函数放在了大括号中,但是,这样真的可以吗??

  1. Sequence;  

这样子也是可以的,就是相当于这样:

{  

  1.        print1();  

  2.        print2();  

  3. ;     


从上面我们可以看到对程序的多个语句加上大括号(并且加上分号),是对整个程序没有影响的

但是,如果是放在if语句中呢?

  1. if(flag)  

  2.         Sequence();  

  3. else  

  4.         printf("123");  

可以知道,上面的程序被替换也就成了这样的:

  1. if(flag)  

  2. {  

  3.          print1();  

  4.          print2();  

  5. };  

  6. else  

  7.         printf("123");  

这时,编译器就会报错,编译错误,大家可以看到这个结构已经不满足if-else结构了

但是,值得注意的是:

单独使用if语句是后面的分号可有可无,就是说:

if(flag)   

  1. {  

  2.          print1();  

  3.          print2();  

  4. };  

等价与:

if(flag)   

  1. {  

  2.          print1();  

  3.          print2();  

  4. }  

责任编辑:#define
首页 | 电气资讯 | 应用技术 | 高压电器 | 电气设计 | 行业应用 | 低压电器 | 电路图 | 关于我们 | 版权声明

Copyright 2017-2018 电气自动化网 版权所有 辽ICP备17010593号-1

电脑版 | 移动版 原创声明:本站大部分内容为原创,转载请注明电气自动化网转载;部分内容来源网络,如侵犯您的权益请发送邮件到[email protected]联系我们删除。