知识点14:预编译

预编译

1,不带参数的宏定义

宏定义命令#define用来定义一个标识符和一个字符串(常数、表达式、格式字符串等)。一般格式为:#define 宏名 字符串不需要在行末加分号
宏替换是以串代替标识符,不分配内存空间。

#define STR "hello, world!"
printf(STR);

注意:

  • 1,如果在串中含有宏名,则不进行替换。printf("This STR is not that STR");//无法替换
  • 2,如果串长于一行,可以在行末用一反斜杠‘ \ ’续行。
#define STR "hello,\
world!"
  • 3,#define命令出现在函数外面,宏名的有效范围为:定义处到文件结尾。
  • 4,可用#undef命令终止宏定义的作用域。
#include <stdio.h>
#define STR "hello"
int main()
{
    
    
	printf(STR);
#undef STR
}

2,带参数的宏定义

带参数的宏定义不是简单的字符串替换,还要进行参数替换。一般格式为:#define 宏名(参数表) 字符串

#include <stdio.h>
#define HHH(a, b) ((a) * (b) + (b))
//为避免出错,各参数、整体都要有括号
int main()
{
    
    
	int x = 5, y = 9;
	printf("%d", HHH(x, y));//输出5*9+9 
	return 0;
} 
#include <stdio.h>
#define MIN(a, b, c) ((a)>(b) ? ((b)>(c)?(c):(b)) : ((a)>(c)?(c):(a))) 
int main()
{
    
    
	int x, y, z;
	scanf("%d%d%d", &x, &y, &z);
	printf("最小值为:%d", MIN(x, y, z));
	return 0;
}

注意:

  • 1,宏名与参数表之间不可以加空格,否则会将空格以后的所有字符都作为替代字符串的一部分。
  • 2,宏定义中,形参不分配内存单元,因此不必声明参数类型。
  • 3,用宏替换代替函数可以提高代码的执行速度(因为不存在函数调用)。
  • 4,进行宏替换时,不应增加或减少内容,只是简单的替换

3,#include命令

在一个源文件中使用#include命令可以将另一个源文件的全部内容包含进来。

双引号与尖括号的区别:
尖括号:编译器以标准方式(到存放C库函数头文件所在目录中寻找所要包含的文件)查找头文件;
双引号:编译器会首先在当前目录下查找头文件,如果没有找到,再以标准方式查找。
一般情况下,调用系统自带的库函数,用尖括号(可节省查找的时间);调用用户自己编写的文件,用双引号(用户自己编写的文件通常在当前目录中,如果不在,可在双引号内写明文件路径)。

一个#include命令只能指定1个被包含的文件,这1个文件中又可以嵌套其它文件。若file1中包含file2,那么预编译后两个文件就成为一个文件,file2内若含有全局变量,则在file1中也可以使用。

4,条件编译

1,#if命令

含义:若#if命令后的参数表达式为真,则编译#if与#endif之间的程序段,否则跳过这段程序。#endif命令用来表示#if段的结束。
一般格式为:

#if 常数表达式  //若常数表达式为真,则该段程序被编译,否则跳过不编译。
	语句段
#endif

#else的作用是为#if为假时提供另一种选择。

#include <stdio.h>
#define NUM 50
int main()
{
    
    
	int i = 0;
	
#if NUM > 50
	i ++;
#else
#if NUM < 50
	i --;
#else
	i += 50;
#endif
#endif//有几个#if 就有几个#endif

	printf("%d", i);
	return 0;	
} 

#elif命令用来建立一种“如果…或者如果…”阶梯状多重编译操作选择,这与if语句嵌套中的else if类似
一般格式为:

#if 表达式
	语句段
#elif 表达式1
	语句段
#elif 表达式2
	语句段
...
#elif 表达式n
	语句段
#endif
#include <stdio.h>
#define NUM 50
int main()
{
    
    
	int i = 0;
	
#if NUM > 50
	i ++;
#elif NUM == 50
	i += 50;
#else
	i --;
#endif

	printf("%d", i);
	return 0;	
} 

2,#ifdef命令

#if条件编译指令中,需要判断符号常量所定义的具体值。但在实际应用中,有时我们并不要求判断具体值,只要知道这个符号是否被定义了即可,此时就不需要使用#if,而用另一种条件编译的方法,即#ifdef与#ifndef命令。

#ifdef表示“如果有定义”,一般格式为:

#ifdef 宏替换名
	语句段
#endif
//含义为:如果宏替换名已经被定义过,则对语句段进行编译;如果没有定义就不编译。

#ifdef可与#else连用,构成的一般格式为:

#ifdef 宏替换名
	语句段1
#else
	语句段2
#endif
//含义为:如果宏替换名已经被定义过,则对语句段1进行编译;如果没有定义,就对语句段2进行编译。

#ifndef表示“如果没定义”,一般格式为:

#ifndef 宏替换名
	语句段
#endif
//含义为:如果宏替换名没有被定义过,则对语句段进行编译;如果定义过就不编译。

同样,#ifndef也可以与#else连用

#ifndef 宏替换名
	语句段1
#else
	语句段2
#endif
//含义为:如果宏替换名没有被定义过,则对语句段1进行编译;如果定义过,就对语句段2进行编译。
//例子
#include <stdio.h>
#define STR "hello"
int main() 
{
    
    
	#ifdef STR
		printf(STR);
	#else
		printf("hhh");
	#endif
	
		printf("jjj");
		
	#ifdef ABC
		printf("ddd");
	#else
		printf(STR);
	#endif
}

3,#indef命令

该命令主要用来删除之前定义的宏定义,使宏名局限在仅需要它们的代码中。一般格式为:

#undef 宏替换名

4,#line命令

#line命令用来改变 _LINE_(存放当前编译行的行号) 与 _FILE_(存放当前编译的文件名) 的内容。

#line 行号["文件名"]

5,#pragma命令

作用是设定编译器的状态,或者指示编译器完成一些特定的动作。

#pragma 参数

参数分为3种情况:
message参数:该参数能够在编译信息输出窗口中输出相应的信息。
code_seg参数:设置程序中函数代码存放的代码段。
once参数:保证头文件被编译一次。

一些预定义替换名

两边都要加下划线_

  • _LINE_ :当前被编译代码的行号
  • _FILE_ :当前源程序的文件名
  • _DATE_ :当前源程序的创建日期
  • _TIME_ :当前源程序的创建时间
  • _STDC_ :用来判断当前编译器是否为标准C(若值为1,则表示符合标准C;否则不符合)

猜你喜欢

转载自blog.csdn.net/Shao_yihao/article/details/113525835