C语言预处理命令(kk-zkx)

    科技2022-07-10  86

    以#号开头的命令称为预处理命令。

    编译是针对单个源文件的,一次编译操作只能编译一个源文件,如果程序中有多个源文件,就需要多次编译操作。

    链接(Link)是针对多个文件的,它会将编译生成的多个目标文件以及系统中的库、组件等合并成一个可执行程序。

    这些在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理、提前处理)。

    预处理主要是处理以#开头的命令,例如#include <stdio.h>等。预处理命令要放在所有函数之外,而且一般都放在源文件的前面。

    预处理是C语言的一个重要功能,由预处理程序完成。当对一个源文件进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。

    编译器会将预处理的结果保存到和源文件同名的.i文件中,例如 main.c 的预处理结果在 main.i 中。和.c一样,.i也是文本文件,可以用编辑器打开直接查看内容。

    C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等,合理地使用它们会使编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。

    栗子

    // 栗子1 #include<stdio.h> //不同平台,引入不同的头文件 #if _WIN32 #include<windows.h> #elif _linux_ #include<unistd.h> #endif int main() { //不同平台下调用不同的函数 #if _WIN32 Sleep(5000); #elif _linux_ sleep(5); #endif puts("hello world!\n"); return 0; }

    #include叫做文件包含命令,用来引入对应的头文件(.h文件)。

    使用尖括号< >和双引号" "的区别在于头文件的搜索路径不同:

    使用尖括号< >,编译器会到系统路径下查找头文件;而使用双引号" ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。 也就是说,使用双引号比使用尖括号多了一个查找路径

    「在头文件中定义定义函数和全局变量」这种认知是原则性的错误!不管是标准头文件,还是自定义头文件,都只能包含变量和函数的声明,不能包含定义,否则在多次引入时会引起重复定义错误。

    宏定义

    #define 叫做宏定义命令,它也是C语言预处理命令的一种。所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。

    //宏定义的一般形式为: #define 宏名 字符串 //#表示这是一条预处理命令,所有的预处理命令都以 # 开头。宏名是标识符的一种,命名规则和变量相同。 //字符串可以是数字、表达式、if 语句、函数等。 //这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符串等同,它不需要双引号。 //程序中反复使用的表达式就可以使用宏定义,例如: #define M (n*n+3*n)

    需要注意的是,在宏定义中表达式(nn+3n)两边的括号不能少,否则在宏展开以后可能会产生歧义。

    对 #define 用法的几点说明

    宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单粗暴的替换。字符串中可以含任何字符,它可以是常数、表达式、if 语句、函数等,预处理程序对它不作任何检查,如有错误,只能在编译已被宏展开后的源程序时发现。宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换。宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名,在宏展开时由预处理程序层层代换。习惯上宏名用大写字母表示,以便于与变量区别。但也允许用小写字母。可用宏定义表示数据类型,使书写方便

    应注意用宏定义表示数据类型和用 typedef 定义数据说明符的区别。宏定义只是简单的字符串替换,由预处理器来处理;而 typedef 是在编译阶段由编译器处理的,它并不是简单的字符串替换,而给原有的数据类型起一个新的名字,将它作为一种新的数据类型。

    带参数的宏定义

    //一般形式 #define 宏名(参数列表) 字符串 //带参调用的一般形式 宏名(实参列表);

    栗子

    #include<stdio.h> #define MAX(a,b) ((a>b)?a:b) int main() { int x,y,max; printf("input two numbers:\n"); scanf("%d %d",&x,&y); max=MAX(x,y); printf("max=%d\n",max); return 0; }

    对带参宏定义的说明

    带参宏定义中,形参之间可以出现空格,但是宏名和形参列表之间不能有空格出现。在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型。而在宏调用中,实参包含了具体的数据,要用它们去替换形参,因此实参必须要指明数据类型。在宏定义中,字符串内的形参通常要用括号括起来以避免出错对于带参宏定义不仅要在参数两侧加括号,还应该在整个字符串外加括号。

    #的用法

    #用来将宏参数转换为字符串,也就是在宏参数的开头和末尾添加引号

    #include <stdio.h> #define STR(s) #s int main() { printf("%s\n", STR(hello world)); printf("%s\n", STR("hello world")); return 0; }

    ##的用法

    ##称为连接符,用来将宏参数或其他的串连接起来

    C语言中几个预定义的宏

    ANSI C 规定了以下几个预定义宏,它们在各个编译器下都可以使用:

    LINE:表示当前源代码的行号FILE:表示当前源文件的名称DATA:表示当前的编译日期TIME:表示当前的编译时间STDC:当要求程序严格遵循ANSI C标准时该标识被赋值为1__cplusplus:当编写C++程序时该标识符被定义。

    栗子

    #include <stdio.h> #include <stdlib.h> int main() { printf("Line : %d\n", __LINE__); printf("Date : %s\n", __DATE__); printf("Time : %s\n", __TIME__); printf("File : %s\n", __FILE__); return 0; }

    C语言#if、##ifdef、#ifndef的用法详解,C语言条件编译详解

    Windows 有专有的宏_WIN32,Linux 有专有的宏__linux__

    栗子

    #include <stdio.h> int main(){ #if _WIN32 system("color 0c"); printf("hello world\n"); #elif __linux__ printf("\033[22;31mhello world\n\033[22;30m"); #else printf("hello world\n"); #endif return 0; }

    #if用法的一般格式

    #if 整形常量表达式1 程序段1 #elif 整型常量表达式2 程序段2 #elif 整型常量表达式3 程序段3 #else 程序段4 #endi

    #if 命令要求判断条件为“整型常量表达式”,也就是说,表达式中不能包含变量,而且结果必须是整数;而 if 后面的表达式没有限制,只要符合语法就行。这是 #if 和 if 的一个重要区别。

    ifdef的用法

    #ifdef 宏名 程序段1 #else 程序段2 #endif

    它的意思是,如果当前的宏已被定义过,则对“程序段1”进行编译,否则对“程序段2”进行编译。

    VS/VC 有两种编译模式,Debug 和 Release。在学习过程中,我们通常使用 Debug 模式,这样便于程序的调试;而最终发布的程序,要使用 Release 模式,这样编译器会进行很多优化,提高程序运行效率,删除冗余信息。

    栗子

    #include <stdio.h> #include <stdlib.h> int main(){ #ifdef _DEBUG printf("正在使用 Debug 模式编译程序...\n"); #else printf("正在使用 Release 模式编译程序...\n"); #endif system("pause"); return 0; }

    ifndef的用法

    #ifndef 宏名 程序段1 #else 程序段2 #endif

    与 #ifdef 相比,仅仅是将 #ifdef 改为了 #ifndef。它的意思是,如果当前的宏未被定义,则对“程序段1”进行编译,否则对“程序段2”进行编译,这与 #ifdef 的功能正好相反。

    #error用法

    //#error 指令用于在编译期间产生错误信息,并阻止程序的编译,其形式如下: #error error_message //例如,我们的程序针对 Linux 编写,不保证兼容 Windows,那么可以这样做: #ifdef WIN32 #error This programme cannot compile at Windows Platform #endif //再如,当我们希望以 C++ 的方式来编译程序时,可以这样做: #ifndef __cplusplus #error 当前程序必须以C++方式编译 #endif

    总结

    Processed: 0.012, SQL: 8