当前位置:文档之家› 预处理指令

预处理指令


#include 指令
#include 指令的作用是指示编译器将该指令所指出的另一个源文件嵌入#include指令所在 的程序中, 文件应使用双引号或尖括号括起来. C 库函数的头文件一般用#include指令在程序开关说明. 例如: #include <stdio.h> 程序中也允许嵌入其它文件, 例如: main() { #include <help.c> } 其中help.c为另一个文件, 内容可为 printf("Glad to meet you here!"); 处理命令的格式 #include "包含文件名" 或 #include <包含文件名 包含文件名" 包含文件名> 包含文件名 包含文件名 两种格式的区别仅在于: (1)使用双引号:系统首先到当前目录下查找被包含文件,如果没找到,再到系统指定 的"包含文件目录"(由用户在配置环境时设置)去查找. (2)使用尖括号:直接到系统指定的"包含文件目录"去查找.一般地说,使用双引号 比较保险.
可变参数的函数
我们在C语言编程中会遇到一些参数个数可变的函数, 例如printf()这个函数,它的定义是这样的: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数 和类型是可变的,例如我们可以有以下不同的调用方法: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s", i, s); 究竟如何写可变参数的C函数以及这些可变参数的函数 编译器是如何实现的呢?现在就这个问题进行一些探讨,希望 能对大家有些帮助.
#error指令
该指令用于程序的调试, 当编译中遇到#error指令就停止编译.其一般形式为: #error 出错信息 出错信息加不加引号都可, 当编译器遇到这个指令时, 显示下列信息并停止编译. Fatal: filename linename error directive 例如:malloc.h定义如下: /* $FreeBSD: src/include/malloc.h,v 1.5 2001/11/07 23:14:31 obrien Exp $ */ #if __STDC__ #error "<malloc.h> has been replaced by <stdlib.h>" #else #include <stdlib.h> #endif 我写一个程序test.c: #include <malloc.h> Main() { Printf("test\n"); } gcc -D__STDC__ -o test test.c In file included from test.c:1: /usr/include/malloc.h:3:2: #error "<malloc.h> has been replaced by <stdlib.h>"
一般格式 #ifdef 标识符 程序段1; [#else 程序段2;] #endif 功能:当"标识符"已经被#define命令定义过,则 功能 编译程序段1,否则编译程序段2. #ifndef ~ #endif命令 命令 格式与#ifdef ~ #endif命令一样,功能正好与之相反.
#pragma
使用宏时,不允许参数发生变化
示例:如下用法可能导致错误. 定义: #define SQUARE( a ) ((a) * (a)) 使用: int a = 5; int b; b = SQUARE( a++ ); // 结果:a = 7,即执行了两次增1. 正确的用法是: b = SQUARE( a ); a++; // 结果:a = 6,即只执行了一次增1.
使用断言来发现软件问题,提高代码可测性
说明:断言是对某种假设条件进行检查(可理解为 若条件成立则无动作,否则应报告), 作用:它可以快速发现并定位软件问题,同时对系 统错误进行自动报警, 好处:断言可以对在系统中隐藏很深,用其它手段 极难发现的问题进行定位,从而缩短软件问题定位 时间,提高系统的可测性. 示例:下面是C语言中的一个断言,用宏来设计的. (其中NULL为0L)
怎样用宏定义多条表达式
示例:下面的语句只有宏的第一条表达式被执行.为了说明问题,for语句的书写稍不符规范. 定义: #define INTI_RECT_VALUE( a, b )\ a = 0;\ b = 0; 使用: for (index = 0; index < RECT_TOTAL_NUM; index++) INTI_RECT_VALUE( rect.a, rect.b ); 正确的用法应为: 定义: #define INTI_RECT_VALUE( a, b )\ do {\ a = 0;\ b = 0;\ } while(0) 使用: for (index = 0; index < RECT_TOTAL_NUM; index++) { INTI_RECT_VALUE( rect[index].a, rect[index].b ); }
用宏定义表达式时,要使用完备的括号
示例:如下定义的宏都存在一定的风险. #define RECTANGLE_AREA( a, b ) a * b #define RECTANGLE_AREA( a, b ) (a * b) #define RECTANGLE_AREA( a, b ) (a) * (b) 正确的定义应为: #define RECTANGLE_AREA( a, b ) ((a) * (b))
用法
#ifdef _EXAM_ASSERT_TEST_ // 若使用断言测试 void exam_assert( char * file_name, unsigned int line_no ) { printf( "\n[EXAM]Assert failed: %s, line %u\n", file_name, line_no ); abort( ); } #define EXAM_ASSERT( condition ) do{if (condition) // 若条件成立,则无动作 NULL; else // 否则报告 exam_assert( __FILE__, __LINE__ )}while(0) #else // 若不使用断言测试 #define EXAM_ASSERT(condition) NULL #endif /* end of ASSERT */ 用断言确认函数的参数. 示例:假设某函数参数中有一个指针,那么使用指针前可对它检查,如下. int exam_fun( unsigned char *str ) { EXAM_ASSERT( str != NULL ); // 用断言检查"假设指针不为空"这个条件 ... //other program code } gcc -D_EXAM_ASSERT_TEST_ -o 目标程序 源程序 gcc -U_EXAM_ASSERT_TEST_ -o 目标程序 源程序
预 处 理 指 令
2006.4.4
Hale Waihona Puke 介预处理指令主要包括 #define #error #if #else #elif #endif #ifdef #ifndef #undef #pragma 由上述指令可以看出, 每个预处理指令均带有符号"#".
#define 指令
定义的一般形式是: #define 宏替换名字符串(或数值) 由#define指令定义后, 在程序中每次遇到该宏替换名时就用所定义的字 符串(或数值)代替它. 例如: 可用下面语句定义TRUE表示数值1, FALSE表示0. #define TRUE 1 #define FALSE 0 一旦在源程序中使用了TRUE和FALSE, 编译时会自动的用1和0代替. 注意: 1. 在宏定义语名后没有";" 2. 在 C程序中习惯上用大写字符作为宏替换名, 而且常放在程序开头.
先来认识一些宏
va_list void va_start( va_list arg_ptr, prev_param ); type va_arg( va_list arg_ptr, type ); void va_end( va_list arg_ptr ); va在这里是variable-argument(可变参数) 的意思.这些宏定义在stdarg.h中,所以用到可 变参数的程序应该包含这个头文件.
#undef指令
#undef指令用来删除事先定义的宏定义, 其一般形 式为: #undef 宏替换名 例如: #define TRUE 1 ... #undef TURE #undef主要用来使宏替换名只限定在需要使用它 们的程序段中.
#ifdef ~ #endif和#ifndef ~ #endif命令
pragma pack(n)
#pragma pack(n) n=1, 2, 4, 8, or 16 内存对齐问题 typedef struct ms1 { char a; int b; } MS1; 如果#pragma pack(1) 则sizeof(MS1)的值是5; 如果#pragma pack(2) 则sizeof(MS1)的值是6; 如果#pragma pack(4) 则sizeof(MS1)的值是8; 如果#pragma pack(8) 则sizeof(MS1)的值是8; gcc编译器默认值是 编译器默认值是4. 编译器默认值是
在所有的预处理指令中,#Pragma指令可能是最复杂的了 作用:是设定编译器的状态或者是指示编译器完成一些特定 作用 的动作. 但是,我们只了解就可以,尽量别去使用. 但是 C和C++编译器认可如下pragmas: alloc_text,comment //注释,auto_inline component //组成部件,inline_depth,pack //包 bss_seg,data_seg,inline_recursion //内嵌递归 pointers_to_members1,check_stack,function intrinsic //内在的,setlocale,code_seg hdrstop,message,vtordisp1,const_seg,warning include_alias,once,init_seg1,optimize //最优化
相关主题