推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

宏定义单引号和双引号

   2023-08-15 网络整理佚名2320
核心提示:(ONE+TWO)注意上面的宏定义使用了括号。宏展开后完全包含在一对括号中,而且参数也包含在括号中,这样就保证了宏和参数的完整性。#运算符出现在宏定义中的#运算符把跟在其后的参数转换成一个字符串。有时把这种用法的#称为字符串化运算符。#nmain(){(%s\n,PASTE(15));}宏定义中的#运算符告诉预处理程序,把源代码中任何传递给该宏的参数转换成一个字符串。

4) 预处理过程 2008 年 11 月 3 日星期一 13:36 预处理过程扫描源代码,对其进行初步转换,并为编译器生成新的源代码。 可以看出,预处理过程是在编译器之前处理源代码。 在C语言中,没有固有的机制来完成以下功能:编译时包含其他源文件、定义宏、编译时根据条件确定是否包含某些代码。 要完成这些任务,您需要使用预处理器。 尽管当今大多数编译器都包含预处理器,但它们通常被认为是独立于编译器的。 预处理过程读取源代码,检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换。 预处理过程还会删除程序中的注释和无关的空白字符。 预处理指令是以#号开头的代码行。 # 符号必须是该行的第一个字符,不包括任何空白字符。 # 后为指令关键字,关键字与# 之间允许有任意数量的空白字符。 整行语句构成了一条预处理指令,该指令将在编译器编译源代码之前对源代码进行某些转换。 以下是一些预处理指令: 指令目的 #空指令,没有效果 #包含源代码文件 #定义宏 #undef 取消定义的宏 #if 如果给定条件为真,则编译以下代码 #ifdef 如果宏已经定义,然后编译下面的代码 #如果宏没有定义,那么编译下面的代码 #elif 如果前面#if给定的条件不为真,当前条件为真,则编译下面的代码 #endif end a #if.. .#else条件编译块#error停止编译并显示错误信息1.文件包含#预处理指令的作用是展开指令处包含的文件。

包含可以是多个,这意味着包含的文件还可以包含其他文件。 标准 C 编译器支持至少八重嵌套包含。 预处理不会检查文件是否已包含在翻译单元中,并防止多次包含该文件。 这样,当多次包含同一个头文件时,通过给出编译时条件,可以达到不同的效果。 例如:#AAA#tc#undef AAA#tc 为了防止只能包含一次的头文件被多次包含,可以使用编译时条件来控制头文件。 例如: # MY_H# MY_H...#endif 在程序中包含头文件有两种格式: # # my.h 第一种方法是用尖括号将头文件括起来。 这种格式告诉预处理器在编译器或外部库的头文件中搜索包含的头文件。 第二种方法是将头文件用双引号引起来。 这种格式告诉预处理器在当前编译的应用程序的源代码文件中搜索包含的头文件,如果没有找到,则搜索编译器附带的头文件。 两种不同包含格式的原因是编译器安装在公共子目录中,而编译后的应用程序安装在它们自己的私有子目录中。 应用程序包含编译器提供的公共头文件和自定义私有头文件。

使用两种不同的包含格式使编译器能够在许多头文件中区分一组通用的头文件。 2. 宏 宏定义了代表特定内容的标识符。 预处理将源代码中出现的宏标识符替换为定义宏时的值。 宏最常见的用途是定义表示值的全局符号。 宏的第二种用法是定义带有参数的宏。 这样的宏可以像函数一样被调用,但是它在调用语句处扩展了宏,并用调用时的实参替换了定义中的形式参数。 1.##预处理指令用于定义宏。 该指令最简单的格式是:首先指定一个标识符,然后给出该标识符所代表的代码。 在下面的源代码中,这些代码用于替换标识符。 这类宏提取一些程序中要使用的全局值,并将它们分配给一些内存标识符。 # 10int array[];for(i=0;i 宏定义并重新编译程序。宏表示的值可以是常量表达式,允许包含之前定义的宏标识符。例如:# ONE 1# TWO 2# THREE (ONE+TWO) 注意,上面的宏定义使用了括号,虽然不是必须的,但为了谨慎起见还是应该加上的,例如: Six=THREE*TWO; 上面这行代码转换为: Six= (ONE+TWO)*TWO;如果没有括号则转为六=ONE+TWO*TWO;。

宏还可以表示字符串常量,例如: # 1.0 (c) 20032。 带参数的 # 指令 带参数的宏看起来有点类似于函数调用。 看一个例子: # Cube(x) (x)*(x)*(x) 可以是任何数值表达式,甚至可以是函数调用,而不是参数 x。 这里再次提醒大家注意括号的使用。 宏展开后,完全包含在一对括号内,参数也包含在括号内,从而保证了宏和参数的完整性。 看一个用法:int num=8+2;=Cube(num); 展开后变成(8+2)*(8+2)*(8+2); 如果没有括号,则变为 8+2*8 +2*8+2。 以下用法是不安全的:=Cube(num++); 如果Cube是一个函数,上面的写法就可以理解了。 但是,由于 Cube 是一个宏,因此它可能会产生副作用。 这里的擦书可不是简单的表达,会产生意想不到的结果。 展开后,它们看起来像这样: =(num++)*(num++)*(num++); 显然,结果是10*11*12,而不是10*10*10; 那么如何安全地使用Cube宏呢? 可能有副作用的操作必须移到宏调用之外:int num=8+2;=Cube(num);num++; 3. 宏定义中出现的#运算符将以下参数转换为字符串。

# 的这种用法有时称为字符串化运算符。 例如: # PASTE(n) #nmain(){(%s\n,PASTE(15));} 宏定义中的 # 运算符告诉预处理器将源代码中传递给宏的任何参数转换为细绳。 所以输出应该是。 4. ##运算符 ##运算符用于将参数连接在一起。 预处理器将 ## 两侧出现的参数组合成单个符号。 请参见以下示例: # NUM(a,b,c) a##b##c# STR(a,b,c) a##b##cmain(){(%d\n,NUM(1,2,3)) ;(%s\n,STR(aa,bb,cc));}最终程序的输出是: 别担心,除非有必要或者宏的使用恰好与手头的工作有关,否则很少有程序员会知道##运算符。 大多数程序员从不使用它。 3. 条件编译指令 条件编译指令将决定哪些代码被编译,哪些不被编译。 编译条件可以根据表达式的值或是否定义了特定的宏来确定。 1. #if 指令 #if 指令检测 make 关键字后面的常量表达式。 如果表达式为真,则编译以下代码,直到出现#else、#elif或#endif; 否则,将无法编译。

2. #endif 指令 #endif 用于终止#if 预处理指令。 # DEBUG 0main(){#if (\n);#(\n);}因为程序定义了DEBUG宏来表示0,所以#if条件为假,后面的代码直到#endif才编译通过,所以程序直接输出。 如果去掉#语句,效果是一样的。 3.#ifdef与##(){#ifdef(yes\n);#endif#(no\n);#endif}#if等价于#ifdef; #如果 ! 相当于#.#else指令# else指令用在#if指令之后,当前面#if指令的条件不成立时,编译#else后面的代码。 #endif 指令将对上述条件块表示中指。 # (){#ifdef (\n);#(Not \n);#(\n);} 5. #elif 指令 #elif 预处理指令结合了#else 和#if 指令的功能。

# (){#ifdef (1\n);#elif (2\n);#(3\n);#endif}程序很容易理解,最终输出是2。 6.其他一些标准指令#error指令将导致编译器显示错误信息,然后停止编译。 #line 指令可以更改编译器用来指示警告和错误消息的文件和行号。 # 指令没有正式定义。 编译器可以自定义其用法。 典型用途是禁止或允许某些烦人的警告消息。

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON