注:所有的一切,都会在意想不到的时候打自己一个大嘴巴子;此章节在学习语言级指令时毫无作用,是绝对用不上的,可是在学习Linux编程时,由于此章节我学习的一塌糊度,导致我连基本的头部定义都该不清楚;现实狠狠的打了我一巴掌;愿君与我共勉!
一、预定义符号
注意:是 _ _ (是杠杠)
__FILE__ //被编译文件的名字(以及所在的目录)__LINE__ // 文件当前的行号__DATE__ // 文件被编译的日期__TIME__ // 文件被编译的时间__STDC__ // 如果编译器遵循 ANSI C ,其值为 1 ,否则未定义//vs2019 是不支持ANSI C(标准c的)
int main() //举例
{
printf("%s\n", __FILE__);
printf("%d\n", __LINE__);
printf("%s\n", __DATE__);
printf("%s\n", __TIME__);
//printf("%s\n", __STDC__);
return 0;
}
二、#define 定义标识符
语法:#define name stuff
举例:
#define M 100 //可以是int类型
#define STR "ABC" //可以是字符串
#define FOR for(;;) //可以是代码#define reg register // 为 register 这个关键字,创建一个简短的名字#define do_forever for(;;) // 用更形象的符号来替换一种实现#define CASE break;case // 在写 case 语句的时候自动把 break 写上。// 如果定义的 stuff 过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠 ( 续行符 ) 。#define DEBUG_PRINT printf("file:%s\tline:%d\t \date:%s\ttime:%s\n" ,\__FILE__,__LINE__ , \__DATE__,__TIME__ )\ : 续行符
注: 在define定义标识符的时候,不要在最后加上 ;
三、#define 定义宏
#define DOUBLE(x) ((x) +(x))int main(){int x=10;int ret=DOUBLE(x);return 0;}
3.2#define 替换规则
3.3#和##
3.3.1使用 # ,把一个宏参数变成对应的字符串
#define PRINT(x,format) printf("the value of " #x "is" format "\n", x)-> #define PRINT(x) printf("the value of " "x" "is "%d\n", x) //会变成这样;int x=10;PRINT(x,"%f");
3.3.2##的作用
#define CAT(x,y) x##y
int main()
{
int cat10 = 50;
printf("%d\n", CAT(cat, 10));
return 0;
} //打印结果是50;
注意:这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。
3.4带副作用的宏参数
3.5宏和函数对比
1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序 的规模和速度方面更胜一筹。
#define MALLOC(num, type)\(type *)malloc(num * sizeof(type))...// 使用MALLOC(10, int);// 类型作为参数// 预处理器替换之后:(int *)malloc(10 * sizeof(int));
3.6#undef
#undef NAME// 如果现存的一个名字需要被重新定义,那么它的旧名字首先要被移除。
3.7命令行定义
四、条件编译
1.单条件编译#if 常量表达式//...#endif// 常量表达式由预处理器求值。如:#define __DEBUG__ 1#if __DEBUG__//..#endif2. 多个分支的条件编译#if 常量表达式//...#elif 常量表达式//...#else//...#endif3. 判断是否被定义#if defined(symbol) //判断的是:是否被定义过,不是真假;#ifdef symbol#if !defined(symbol)#ifndef symbol4. 嵌套指令#if defined(OS_UNIX)#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif#elif defined(OS_MSDOS)#ifdef OPTION2msdos_version_option2();#endif#endif
int main()
{
#if 1
printf("hehe\n");
#endif
return 0;
}#define M 0int main()
{
#if M==1 //也可以放表达式;
printf("hehe\n");
#endif
return 0;
}
//#define WIN 0#define WIN
int main()
{
#ifdef WIN
printf("hehhe\n");
#endif
return 0;
}
五、头文件被包含的方式
5.1本地文件包含
#include "filename"
5.2库文件包含
#include <filename.h>
5.3多重嵌套
如果出现了多重嵌套问题,比如源文件引用了两份头文件;可以使用条件编译解决
防止被大量重复引用;
#ifndef __TEST_H__ //其中__TEST_H__ 只是一种test.h文件名的写法,一种处理;是程序员自己定义的宏,不是系统自带的;第一个头文件里定义了这个宏,以下再引用这个头文件就不会被编译;#define __TEST_H__// 头文件的内容#endif //__TEST_H__
#pragma once //另一种写法