1、先说“#if 0/#if 1 ... #endif”的作用,楼上诸位或多或少都说到了一点,但都没有说到关键的地方。我们知道,C标准不提供C++里的“//”这样的单行风格注释而只提供“/* */”这样的块注释功能,我们通常使用它写代码中说明性的注释文字(注释作用)以及在调试时关闭某段代码对编译器的可见性(屏蔽作用),当然,这里所谓的“注释作用”和“屏蔽作用”是我们从功能上下的主观定义,对预处理器而言,两者并无任何区别。对于前者,因为“注释”中不会再出现“注释”和“需要屏蔽的代码段”,所以不会有嵌套的需求,所以通常不会有问题;而对于后者,当我们在调试程序时需要“屏蔽”某段代码时,该段代码中可能包含着前述的“注释”和/或“已被屏蔽的代码段”,这时就产生了“/* */”嵌套使用的需求,但SB的C标准恰恰不允许我们这么干。当你试图使用嵌套的块注释功能时,会发现预处理器把最外层注释的开始和最内层注释的结尾这两者之间的内容处理成了注释,而其后一直到最外层注释结尾的内容被当作了“有效代码”——这显然会引起若干语法错误而导致编译中止。高手们开动脑筋想到了“#if 0 ... #endif”,它同样由预处理器进行处理,同样可以“屏蔽”一段代码,你想把说明文字写在里面也可以,这些和“/* */”都一样,但不一样的是:第一它允许嵌套(层数上限由预处理器决定)、第二你随时可以把“#if 0”改成“#if 1”来取消对某段代码的“屏蔽”——很卓越的特性,快抛弃笨拙的“/* */”吧!它唯一的缺点就是在编辑器中没有“注释”该有的文本显示样式。
2、现在再来说说2楼提到的自动变量局部化的问题:
------------------------------------------------
通过google,得知:
#if 0
code
#endif
(1)code中定义的是一些调试版本的代码,此时code完全被编译器忽略。如果想让code生效,只需把#if 0改成#if 1
(2)#if 0还有一个重要的用途就是用来当成注释,如果你想要注释的程序很长,这个时候#if 0是最好的,保证不会犯错误。(但是林锐的书上说千万不要把#if 0 来当作块注释使用)
#if 1可以让其间的变量成为局部变量。
(3)这个结构表示你先前写好的code,现在用不上了,又不想删除,就用这个方法,比注释方便。
------------------------------------------------
通过我上面说的第一点,我们可以知道,对“#if/#endif”的处理是预处理器完成的,而预处理器的唯一工作就是作“文字替换”的“预处理”工作,它并不负责常数符号表的生成、变量存储空间的分配、代码的重定位等工作,那么完全是给预处理器看的“#if/#endif”怎么能控制变量的生存期、怎么能决定变量可以在哪里定义??
打开编辑器,写下如下代码:
===========================
volatile unsigned char a;
unsigned int main(void)
{
a = 0;
#if 1
unsigned char *p = &a;
*p = 255;
#endif
return 0;
}
===========================
存成.c文件后用任何C编译器(不包括C++编译器)编译,都会在红字那一行报错——为什么呢?因为预处理器进行“预处理”的时候发现if的条件表达式为“真”,所以它把那段代码块留下了,而只把代码块前后的“预处理指示符号(或者叫做预处理命令)”给清除掉了,这样,预处理后的结果交给编译器“翻译”的时候,它发现在一个函数(在这里为main函数)内部的表达式语句(在这里是a = 0;)之后发现了变量声明/定义语句(在这里是声明并定义指针变量p的语句)——按照编译器的规则,这是一个错误,所以它拒绝接受这样的输入并开始抱怨(中止编译、给出错误信息)。
至此,关于“#if 1/#if 0/#endif”,我要说的就全说完了,欢迎大家拍砖哈~_~
下面再多啰嗦两句。
--------------------------
那么我们能不能享受C++程序员所得到的“将变量的定义放在它开始被需要的地方”这种待遇呢?
答案是肯定的。
手段?
——代码块!
用一对大括号括起来的代码块的首部,可以声明/定义变量,这些变量的作用域仅限于该代码块内部,当然,这些变量声明/定义语句也必须全部位于该代码块中第一个表达式语句之前,不然会出现上面描述的错误,不过好在C编译器允许我们在代码块中嵌套定义代码块,所以大家从现在开始,大可不必在函数的开头定义一大堆变量,那里只要写一些在整个函数执行过程当中都需要的变量的声明/定义语句就好了;至于循环结构的循环变量等这些生存期不长的变量,它们的声明/定义语句完全可以放在一个用一对大括号括起来的代码块的首部。
啰嗦了这么多,写一小段代码证明一下我的说法,呵呵:
===========================
volatile unsigned char a;
unsigned int main(void)
{
a = 0;
{ //注
unsigned char *p = &a;
*p = 255;
}
return 0;
}
===========================
注:我个人的代码书写风格是大括号独占一行并且缩进量与父语句相同,函数体、循环体、case、if四者中的语句增加缩进,但如上的“代码块”则不增加。
存盘、编译。
Hmmmm,编译器不再在红色的行给出错误提示了,编译通过,得证~_~
转自:http://www.cnblogs.com/MichaelOwen/articles/2128733.html
分享到:
相关推荐
### #if、#endif、!defined 的意义与用法详解 在编程中,预处理器指令是一种非常实用且强大的工具,特别是在 C 和 C++ 这样的编程语言中。本文将详细介绍 `#if`、`#endif` 以及 `!defined` 的含义与用法。 #### 一...
#endif 命令是用来结束#if、#ifdef、#ifndef 命令的作用域,它们之间的代码将被编译或跳过。 头文件中的#ifndef 在头文件中,我们通常使用#ifndef来避免头文件被多次包含,从而避免声明冲突。 例如: ``` #ifndef...
#ifdef_#else_#endif_#if_#ifndef的用法.txt
"#ifdef,#else,#endif和#ifndef的用法" #ifdef、#else、#endif 和#ifndef 是 C/C++ 预处理命令中条件编译的四个基本指令,它们可以帮助开发者在编译前对代码进行选择性编译,从而实现代码的灵活使用和高效编译。 #...
defined(AFX_STDAFX_H__61AA8837_C4E8_11D1_B97C_783BA9000000__INCLUDED_) #define AFX_STDAFX_H__61AA8837_C4E8_11D1_B97C_783BA9000000__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= ...
在C语言中,`#ifndef`、`#define`、`#endif`等宏是预处理器指令,它们用于实现条件编译,这是一种根据特定条件决定是否编译代码块的机制。预处理器是编译过程的第一步,它在实际编译之前处理源代码,主要任务之一...
条件编译指令在优化代码、处理编译时条件、实现跨平台代码以及管理大型项目中起着关键作用。它们使得程序员能够在不改变基本代码结构的情况下,根据需求启用或禁用某些特性,从而提高了代码的可维护性和可扩展性。...
#if !defined(AFX_STDAFX_H__C4B5DA9B_21EA_47D6_9253_A4245E58FBF5__INCLUDED_) #define AFX_STDAFX_H__C4B5DA9B_21EA_47D6_9253_A4245E58FBF5__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER >...
此选项用于定义预处理符号,可以在程序中使用`#if`、`#elif`和`#endif`进行条件编译。多个符号之间用分号分隔。 例如: ```bash csc /define:DEBUG;TRACE Program.cs ``` #### /doc: 此选项用于生成XML格式的文档...
#define USOC_EN 0u //0为禁止uC/OS,大于0则启动uC/OS #if USOC_EN > 0u #include "ucos_ii.h" //uC/OS-II系统函数头文件 #include "BSP.h" //与开发板相关的函数 #include "app.h" //用户任务函数 #endif ...
defined(AFX_STDAFX_H__0B5A611D_24E3_40B6_A995_4850C6DC778E__INCLUDED_) #define AFX_STDAFX_H__0B5A611D_24E3_40B6_A995_4850C6DC778E__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000...
本文将深入探讨`#ifndef`、`#define`和`#endif`这三个预处理器指令,它们在创建头文件保护(Header Guards)时起着关键作用。 `#ifndef` 是 "If Not Defined" 的缩写,它的作用是检查指定的宏是否已经定义过。如果...
#if !defined(AFX_STDAFX_H__58C73787_1231_40B3_A8BC_2F7670ABA3D7__INCLUDED_) #define AFX_STDAFX_H__58C73787_1231_40B3_A8BC_2F7670ABA3D7__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER >...
defined(AFX_DQPLOT_H__0D536D37_5CF1_11D1_AED1_0060973A08A4__INCLUDED_) #define AFX_DQPLOT_H__0D536D37_5CF1_11D1_AED1_0060973A08A4__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= ...
#include <sys/cdefs.h> ...#if 0 static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95"; #else __RCSID("$NetBSD: cp.c,v 1.58 2012/01/04 15:58:37 christos Exp $"); #endif #endif /* not lint */
#endif 命令是#if, #ifdef, #ifndef 这些条件命令的结束标志。 9. defined defined 命令用来测试某个宏是否被定义。defined(name): 若宏名被定义,则返回 true。 例如: ```c #if defined(_DEBUG) // ... #endif...
#if宏是C语言预处理命令中的一种,它的作用是:当指定的表达式值为真时,编译程序段1,否则编译程序段2。它的基本形式是: ``` #if 表达式 程序段 1 #else 程序段 2 #endif ``` 其中,#if宏后面跟着一个表达式,如果...
#include "../Libqrencode 4.0.2/include/qrencode.h" #if _DEBUG #pragma comment(lib,"../Libqrencode 4.0.2/debug/lib.X86/LibQRd.lib") #pragma comment(lib,"../Libqrencode 4.0.2/debug/lib.X64/LibQRd.lib") ...
#### #ifdef、#ifndef 和 #if 的基本用法 ##### #ifdef `#ifdef` 是最常用的条件编译指令之一,用于检查某个宏是否已经被定义。其语法格式如下: ``` #ifdef 标识符 // 程序段1 #else // 程序段2 #endif ``` 如果`...