#define
#define定义的宏可以出现在程序的任何位置
#define定义之后的代码都可以使用这个宏
#define定义的宏常量本质为字面量
#define表达式不能出现递归定义
C语言中的内置宏
ANSI C 规定了以下几个预定义宏,它们在各个编译器下都可以使用:
LINE:表示当前源代码的行号;
FILE:表示当前源文件的名称;
DATE:表示当前的编译日期;
TIME:表示当前的编译时间;
STDC:当要求程序严格遵循ANSI C标准时该标识被赋值为1;
__cplusplus:当编写C++程序时该标识符被定义。
__WIN32:当在window平台下编写程序时被定义
linux:当在linux平台下编写程序时被定义
条件编译使用分析
条件编译在行为上类似c语言中的if…else…;
条件编译在预处理期进行分支判断;
我们可以通过命令行来定义宏
格式:gcc –Dmacro=value file.c 或者 gcc –Dmacro file.c
#include
include将已经存在的文件内容嵌入到当前文件中来;间接包含同样会嵌入文件内容;多次包含了同一文件会嵌入多次,出现重复定义,程序出错。
现代软件工程涉及到的文件众多,为了避免重复调用头文件,防止程序出错,一般在头文件前使用如下语句:
#ifndef headname_h
#define headname_h
//头文件体
#endif
#error
#error用于生成一个编译错误消息
用法:#error message message是我们要输出的语句,但不需要双引号
类似的:#warning用于生成编译警告
例如:
#ifndef __cplusplus
#error This file should be processed with C++ compiler.
#endif
//__cplusplus是c++内置的宏,在C语言中没有定义,如果使用c编译,则#error执行,编译无法完成。
#line
#line用于强制自定义新的行号和编译文件名,并对源程序的代码进行重新编号。
用法:#line number filename //filename可省略
#line编译指示字的本质是重定义_LINE_和_FILE_
#pragma
#pragma用于指示编译器完成一些特定的动作
#pragma所带有的指示字很多是编译器特有的,不可移植
编译器将忽略不认识的#pragma指令
#pragma message 用于在编译时输出消息到编译输出窗口
#pragma pack(number) 用于指定内存以number字节对齐
内存对齐
不同类型的数据在内存中按照一定的规则排列
下面是以4字节对齐的例子:
需要进行内存对齐的原因:CPU对内存的读取不是连续的,而是分成块读取的,块的大小只能是1、2、4、8、16…字节;当被读取的数据元素未进行内存对齐时,需要2次总线周期访问内存,性能上有影响;同时对于一些硬件平台而言,只能从规定的相对地址读取特性类型的数据,否则会产生硬件异常。
编译器在默认情况下进行4字节内存对齐。
#标识符
#标识符用于在预处理期将宏参数转换成字符串;
#的转换作用是在预处理期完成的,因此只在宏定义中有效。
例如:
#define Call(f, p) (printf(“Call function %s\n”, #f), f(p))
int square(int n){return n* n;}
int main()
{
printf(“result = %d\n”, Call(square, 4));
return 0;
}
## 标识符
##用于在预处理期粘连两个标识符
#的转换作用是在预处理期完成的,因此只在宏定义中有效
例如:
#define STRUCT(type) typedef struct _tag_##type type;\
struct _tag_##type
STRUCT(student)
{
char* name;
int id;
};
int main()
{
student std;
return 0;
}