C语言--预处理

文章目录

  • 一、宏定义
    • [   1、宏定义](#   1、宏定义)
    • [   2、有参宏和无参宏](#   2、有参宏和无参宏)
    • [   3、​​预定义宏​​:C语言预处理器提供了一些内置的宏,用于获取编译时的信息。](#   3、预定义宏:C语言预处理器提供了一些内置的宏,用于获取编译时的信息。)
  • 二、文件包含
    • [   1、标准方式:](#   1、标准方式:)
    • [   2、通用方式:](#   2、通用方式:)
    • [   3、包含保护](#   3、包含保护)
  • 三、条件编译
    • [   1、如果标识符被定义过](#   1、如果标识符被定义过)
    • [   2、如果标识符未被定义过](#   2、如果标识符未被定义过)
    • [   3、根据表达式判定](#   3、根据表达式判定)
    • [   4、实例:](#   4、实例:)
  • 四、编译器配置
    • [   1、Pragma 指令格式](#   1、Pragma 指令格式)
    • [   2、Pragma 指令常用参数](#   2、Pragma 指令常用参数)
      • [     #pragma message](#pragma message)
      • [     #pragma code_seg](#pragma code_seg)
      • [     #pragma once](#pragma once)
      • [     #pragma hdrstop](#pragma hdrstop)
      • [     #pragma resource](#pragma resource)
      • [     #pragma warning](#pragma warning)
      • [     #pragma disable](#pragma disable)
      • [     #pragma data_seg](#pragma data_seg)

C语言预处理是C语言编译过程中的一个重要阶段,它在编译器对源代码进行编译之前,由预处理器对源代码进行一系列文本处理操作。预处理指令以井号(#)开头,它们不是C语言的语句,因此不需要以分号(;)结尾。

一、宏定义

宏定义的作用就是在程序中某段代码的一个别名,宏定义主要是为程序调试、移植等提供便利是一个非常实用的功能。

1、宏定义

所有的宏命令行都以符号"#define"开头,并且结尾不用分号,

例: #define PI 3.14

宏定义的作用是在编译处理时,将源程序中所有标识替换成语名序列,宏定义分为有参宏和无参宏。

需要注意的是,宏名一般用大写字母,以便于与变量名的区别,在编译与处理时,宏名与字符串进行替换时,不做语法检查,只是简单的字符替换,只有在编译时才对已展开的宏名的源程序进行语法检查,宏名的有效范围是从定义位置到文件结束,如果需要终止红定义的作用域可以用 "#undef"命令,

例如:

#define PI 3.14

......

#undef PI

2、有参宏和无参宏

无参宏指的是执行单一的替换功能的宏定义,在使用无参红时要注意以下两个问题,

1.宏定义时可以引用已经定义的宏名如以下所示:

#define R 2.0

#define PI 3.14

#define L 2R PI

2.对程序中用双引号括起来的字符的字符串内的字符,不进行宏定义的替换操作。

有参宏可以让我们在宏定义时,还可以带参数扩大宏的应用范围,有参宏的格式:

#define 标识符(参数表) 字符串

它的作用是在编译预处理时,将原程序中所有的标识符替换成字符串,并且将字符串中的参数用实际使用的参数替换,

例如:

#define S(a,b) (a*b)/2

需要注意的是,在宏定义时,宏名和参数之间不能有空格,否则空格后面的所有字符序列都作为替换的字符串,带参数的宏展开时,只做简单的字符和参数替换,不进行任何计算操作,所以一般在宏定义时字符串中的形式参数外面加一个小括号

例如:

#define L( r ) 2*PI*r

如果输入 L(2+3) 则编译后变为 2*3.14*2+3 不是2*3.14*5

解决方法:

#define L( r ) 2*PI*( r )

3、​​预定义宏​​:C语言预处理器提供了一些内置的宏,用于获取编译时的信息。

宏        描述

FILE    当前源文件名(字符串)

LINE    当前行号(整数)

DATE    编译日期(字符串)

TIME    编译时间(字符串)

STDC    如果编译器遵循ANSI C标准,则定义为1。

二、文件包含

文件包含的功能是将指定的文件内容嵌入到一个原文件中,文件包含共有以下两种格式:

1、标准方式:

只按照标准方式在C语言编译器的C函数库头文件中查找要包含的文件。

#include <> 一般用于包含系统头文件,诸如 stdlib.h 、stdio.h 、iostream等;

#include <xxxx.x>

2、通用方式:

先在原文件所在的目录中查找要包含的文件,若未能找到,则在按照标准方式查找。

#include " " 一般用于包含自定义头文件,如test.h、declare.h等

#include "xxxx.x"

3、包含保护

为了避免头文件被重复包含,通常会在头文件中使用​​包含保护:

c 复制代码
			#ifndef MY_HEADER_H
			#define MY_HEADER_H
			// 头文件内容
			#endif

三、条件编译

#ifdef #ifndef #if #else #endif

条件编译一般用于某种条件判断是否要编译某一段代码,常用的格式如下:

1、如果标识符被定义过

c 复制代码
			#ifdef 标识符
					/*程序段1*/
			#else
					/*程序段2*/
			#endif 

2、如果标识符未被定义过

c 复制代码
			#ifndef 标识符
				/*程序段1*/
			#else
				/*程序段2*/
			#endif

3、根据表达式判定

c 复制代码
			#if 表达式
				/*程序段1*/
			#else
				/*程序段2*/
			#endif 

4、实例:

c 复制代码
			#include <stdlib.h>
			#include <stdio.h>
			#define ABC 123456
			
			int main()
			{
			#ifdef ABC 
				printf("定义了ABC !\n");
			#else
				printf(L"未定义ABC !\n");
			#endif
			#ifndef  CBA
				printf("未定义CBA!\n");
			#endif
				system("pause");
			    return 0;
			}

四、编译器配置

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

#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。

1、Pragma 指令格式

格式一般为:

#pragma Para //其中Para 为参数。

2、Pragma 指令常用参数

#pragma message

Message 参数能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。

其使用方法为:

#pragma message("消息文本")

当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

#pragma code_seg

设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

格式:

#pragma code_seg(["section-name"[,"section-class"]])

#pragma once

只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。

#pragma hdrstop

#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。

#pragma resource

#pragma resource ".dfm"表示把.dfm文件中的资源加入工程。*.dfm中包括窗体外观的定义。

#pragma warning

#pragma warning(disable:450734;once:4385;error:164)

等价于:

#pragma warning(disable:450734)//不显示4507和34号警告信息

#pragma warning(once:4385)//4385号警告信息仅报告一次

#pragma warning(error:164)//把164号警告信息作为一个错误。

#pragma disable

在函数前声明,只对一个函数有效。该函数调用过程中将不可被中断。一般在C51中使用较多。

#pragma data_seg

用#pragma data_seg建立一个新的数据段并定义共享数据,其具体格式为:
**            #pragma data_seg("shareddata")
           HWND sharedwnd=NULL;//共享数据
           #pragma data_seg()**

1、#pragma data_seg()一般用于DLL中。也就是说,在DLL中定义一个共享的有名字的数据段。

最关键的是:这个数据段中的全局变量可以被多个进程共享,否则多个进程之间无法共享DLL中的全局变量。

2、共享数据必须初始化,否则微软编译器会把没有初始化的数据放到.BSS段中,从而导致多个进程之间的共享行为失败。

相关推荐
郝学胜-神的一滴3 天前
深入解析C++命令模式:设计原理与实际应用
开发语言·c++·程序人生·软件工程·命令模式
紫金桥软件3 天前
组态软件和实时数据库区别大吗?
数据库·物联网·软件工程·scada·监控组态软件
HLJ洛神千羽4 天前
人机交互的软件工程方法实验报告(黑龙江大学)
人机交互·软件工程
文火冰糖的硅基工坊4 天前
[人工智能-大模型-97]:大模型应用层 - 随着技术的发展,软件工程与软件开发过程提效演进阶段(工具化 → 流程化 → 智能化)和未来的展望。
人工智能·软件工程
张较瘦_5 天前
[论文阅读] AI + 软件工程 | 从“能用”到“耐用”:LLM生成软件的老化陷阱与研究突破
论文阅读·人工智能·软件工程
雾江流7 天前
快指点击器 1.1.9 | 支持多点操作、自动化脚本,操作记录等功能,快速解放双手
运维·自动化·软件工程
lapiii3588 天前
14天极限复习软考-day5 软件工程 、UML
软件工程·uml
雾江流8 天前
LocalDream 2.1.2 |在手机设备上运行SD模型,支持文本到图像生成和图像重绘,无任何限制
软件工程
雾江流9 天前
vidhub v1.3.13 |聚合主流网盘,自动刮削整理影视资源,有网盘会员的可入,或者使用不限速网盘
软件工程
数学小牛马10 天前
现代软件工程课程 个人博客作业2-结对编程项目总结
软件工程·结对编程