预编译命令

news/2025/11/26 23:09:39/文章来源:https://www.cnblogs.com/h-elden/p/19274913

预编译命令

#include

#include<文件名> 或者 #include"文件名"

功能:

先由预处理器删除这条指令,然后把指定的文件插入该命令行位置,使指定文件和当前的源程序文件连成一个文件

注意:

  1. 一个include命令只能指定一个被包含文件。

  2. 使用尖括号:在包含文件目录中查找(即由用户事先在设置环境时设置的);使用双引号:首先在当前的源文件的目录中查找,若未找到才去包含目录中查找。

  3. 文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。

  4. 若在file1.c文件中写入:(注意前后顺序!)

    #include<file2.c>
    #include<file3.c>
    

    则file1.c和file3.c都可以使用file2.c的内容,而不必在file3.c中重复包含。为防止文件内容重复被包含就要合理使用条件编译

  5. 被包含文件(file2.c)与其所在的文件(即用#include命令的源文件file1.c)在预编译后已成为同一个文件
    因此如果file2.c中有全局静态变量,它也在file1.c文件中有效,不必用extern声明。

重复包含的解决方案:

1.如果头文件首尾均加上条件编译语句,就不会出现重复定义的编译错误。

这三行语句也可用一行 #pragma once 语句替代。详情

"head1.h"

#ifndef _HEAD1_H_
#define _HEAD1_H_
struct Stu{string name;int age;
};
#endif

"main.cpp"

#include "head1.h"
#include "head1.h"
int main(){return 0;
}

2.给可能重复在不同头文件中定义的结构体使用条件编译,就不会出现重复定义的编译错误。

"head1.h"

#ifndef _HEAD1_H_
#define _HEAD1_H_#ifndef _Stu
#define _Stu
struct Stu{string name;int age;
};
#endif#endif

"head2.h"

#ifndef _HEAD2_H_
#define _HEAD2_H_#ifndef _Stu
#define _Stu
struct Stu{string name;int age;
};
#endif#endif

"main.cpp"

#include "head1.h"
#include "head2.h"
int main(){return 0;
}

#define

无参宏定义

形式:

#define 标识符 字符串

功能:

用于指定标识符(宏名)代替字符序列(宏体)

#表示这是一条预处理命令,define为宏定义命令,“标识符”为所定义的宏名,“字符串”可以是常数、表达式、格式串等。

对源程序进行编译时,先由预处理程序进行宏置换,即用表达式代换所有宏名,然后再进行编译

注意:

1.宏定义的位置任意,但一般情况下放在函数外面。

2.习惯上宏名用大写字母表示,以便与变量区别。但也可以用小写。

3.宏名的有效范围为从定义命令开始到 #undef PI 语句 或者 本源文件结束(如果没有#undef语句)

4.宏定义是用宏名表示一个字符串,只是进行简单的代换,不做任何正确性检查。如有错误,只能在编译已被宏展开之后的源程序时发现。

5.宏定义不是说明或语句,行末不必加分号;如加,一起置换。例:#define P printf("\n");

6.宏名在源程序中被引号括起来,则预处理程序不对其进行宏置换。例:printf("PI"); 输出:PI

7.宏定义允许嵌套但不允许递归。#define max max+10 是错误的

#define width 40         //长方形的宽 
#define length width+20  //长加宽,这里运用了嵌套 
var = length*2;          //计算周长

8.宏定义必要时要加圆括号,例如上例中宏展开为 var = 40+20 * 2 计算错误
应改为 #define length (width+20) 其宏展开为 var = (40+20) * 2 计算正确

9.宏定义可表示数据类型 #define LL long long ,但与用typedef定义数据说明符有区别:

宏定义只是简单的字符串代换,在预处理时完成;

typedef定义的数据说明符是在编译时处理的,它不是进行简单的代换,而是对类型说明符重新命名。

#define STU1 int *
typedef (int *) STU2
STU1 a, b;

宏代换后变成 int *a, b; a 是指向整型的指针变量b整型变量

STU2 a, b;

由于STU2是一个类型说明符,所以此时 ab 都是指向整型的指针变量

10.对“输出格式”进行宏定义可以减少书写工作量。

 #define P printf#define D "%d\n"#define F "%f\n"int a = 3;float b = 2.1;P(D F,a,b); 

含参宏定义

形式:

#define 宏名(形参表) 字符串

功能:

宏展开:形参用实参替换,其他字符保持不变。字符串中包含括号中的形参。

注意:

1.宏体及各形参外一般应加圆括号,避免宏展开后运算优先级发生改变。

#define POWER(x) ((x)*(x))

2.宏名和形参表间不能加空格

3.宏定义可以实现某些函数的功能。

4.宏定义中的形参是标识符,而宏调用中的实参可以是表达式。

5.含参宏定义和函数的区别

(1) 函数调用先求表达式的值,再带入形参。宏调用先进行宏展开,即字符串的替换。
POWER(i++) 会运行 (i++) * (i++) ,平方后 i 会自加 2 次而不是一次。

(2) 宏调用是通过宏展开完成的,在编译阶段进行,不占运行时间,只占编译时间
函数调用是在程序运行时进行的,占运行时间(包括分配内存单元,保留现场,值传递和返回)

(3) 带参宏定义不存在类型问题,宏名无类型,参数也无类型,也不需要分配内存空间
而函数却要求形参和实参类型必须保持一致,调用时也需要给形参分配临时的储存空间。

(4) 多次宏调用会使程序变长,而函数调用多次也不会使程序加长。

(5) 调用函数只能得到一个返回值,而用宏则可以设法得到多个结果。

连接符

字符串化操作符#
功能:

用于宏定义中,表示把参数字符串化,即把一个参数转换成字符串。

实例:
#include<iostream>
using namespace std;
#define PASTE(n) "abcdef"#n
int main() {printf("%s\n", PASTE(15));			//输出:abcdef15return 0;
}
符号连接操作符##
功能:

连接符,连接两个参数作为一个标识。

实例:

1.连接

#include<iostream>
using namespace std;
#define NUM(a,b,c) a##b##c				//连接
#define STR(a,b,c) a##b##c
int main() {printf("%d\n", NUM(1, 2, 3));		//输出:123
//	printf("%s\n", STR(aa, bb, cc));	//一些编译器会报错return 0;
}

2.变量的命名

#include <iostream>
using namespace std;
#define VAR(v) num##v				//变量的命名
int main() {int VAR(First) = 1;int VAR(Tail) = 2;int VAR(Cur) = 3;printf("%d %d %d", numFirst, numTail, numCur);	//输出:1 2 3return 0;
}

注意:

下面是一个错误示例:

#include <iostream>#define TRR1T 1
#define TRR2T 2#define MM(x) TRR##x##T * 10using namespace std;int main() {int i;cin >> i;cout << MM(2);			//正确输出 20 
//	cout << MM(i);			//[错误]'TRRiT' was not declared in this scope; did you mean 'TRR1T'?return 0;
}

宏定义的原理是原样替换,并不会根据 \(i\) 的值替换成 TRR1T ,而是直接替换成 TRRiT

一个可以参考的修改方案是:

#include <iostream>#define TRR1T 1
#define TRR2T 2#define MM(x) TRR##x##T * 10using namespace std;int main() {int i;cin >> i;switch (i) {case 1:cout << MM(1);	break;case 2:cout << MM(2);break;default:cout << "ERROR";break;}return 0;
}
字符化操作符#@
功能:

只能用于有传入参数的宏定义中,且必须置于有宏体的参数名前。作用是将传入的单字符参数名转换成字符,以一对单引号括起来。

实例:
#include <iostream>
using namespace std;
#define ToChar(c) #@c
int main() {putchar(ToChar(2));			//输出:2return 0;
}

#if

功能:

条件编译在预编译中执行,可以实现某些语句正常编译或者完全忽略,而程序中的if语句依然会全文编译。

形式:

1.

#if 常数表达式1程序段1
#elif 常数表达式2	//(可不写)程序段2
#else          	   //(可不写)程序段3
#endif

2.

#ifdef 标识符    //如果此宏名已经被定义(#define)过程序段1
#else          //(可不写)程序段2
#endif

3.

#ifndef 标识符      //如果此宏名没有被定义(#define)过程序段1
#else         	   //(可不写)程序段2
#endif

实例:

#include<iostream>
using namespace std;
int main() {
#ifndef ONLINE_JUDGE			//在测评网站上一般都有定义的这个宏freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endifint a, b;cin >> a >> b;cout << a + b;return 0;
}

#pragma

1.#pragma message("消息文本")

功能:

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

实例:

#include <iostream>
using namespace std;
#pragma message("This is a test.")
int main() {return 0;
}

点击“编译”后,编译器窗口中提示:[说明] '#pragma message: This is a test.'

2.#pragma once

功能:

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

3.#pragma warning(command:错误代码)

功能:

设置警告信息状态。

disable:4066 //屏蔽代码为4066的警告信息

once:4066 //仅报告一次代码为4066的警告信息

error:4066 //将代码为4066的警告信息作为一个错误

4.#pragma comment(comment-type,"commentString")

说明:

comment-type 是一个预定义的标识符,指定注释的类型,一般用来加载静态库。

commentString 是一个为 comment-type 提供附加信息的字符串。

5.#pragma pack()

说明:

指定对齐长度:用于结构体、联合中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/977748.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 KEYDIY KD-MP: Add Keys for MLB MQB – Key Identification, Data, Calculation

The Key Replacement Challenge: Why Modern Vehicles Are a Headache For European and American automotive repair shops and car owners, replacing keys for MLB and MQB systems in Volkswagen Group vehicles (…

把 CLI 搬上 Web:在内网打造“可二开”的 AI IDE,为什么这条路更现实? - 指南

把 CLI 搬上 Web:在内网打造“可二开”的 AI IDE,为什么这条路更现实? - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-…

[LangChain] 23. 回调机制

invoke/stream() 方法,方法签名如下: invoke/stream(input: Input,options?: RunnableConfig ): AsyncGenerator<StreamEvent<Output>>1. 输入参数 (input) 类型:Input 与 invoke() 方法保持一致:如果…

本地环境自建的es重启,http和https访问es,nested数据类型及设置es别名

本地环境自建的es重启,http和https访问es,nested数据类型及设置es别名本地环境自建的es重启,http和https访问es,nested数据类型及设置es别名 link:https接口的支持判断,http升级到https需求https://www.cnblogs.com/…

一文入门 LangChain 开发

2024-05-22 [[Ollama]] [[N_LangChain]] [[N_LangGraph]] LangChain github langchain 项目页 github langgraph 项目页 官方文档 introduction 官方文档 0.2 introductio 0.2 langserve 官方文档 0.1 Components La…

freedom of speech

but N cannot be bad. I think its just the difference between cultures.

七、设备模型

一、概述kobject内核抽象出来的通用对象,对应/sys目录下的一个文件 kset是kobject的一个扩展,一个kset尅包含多个kobject,将多个kobject通过parent进行关联,实现了层次化的结构 sysfs虚拟文件系统,向用户空间提供…

Scrum冲刺阶段 Day Three

一、站立会议纪要 1. 已完成工作 后端开发:设计用户与文件表结构 实现注册登录接口 实现文件上传接口 实现全局异常处理 封装请求拦截器前端开发:搭建前端基础框架 开发注册登录页面2. 今日计划工作实现文件列表查询…

鼎鉴时代锋芒 智启品牌新章 ——2025品牌智鉴榜荣耀登临

当全球产业重构与消费升级浪潮澎湃交汇,品牌早已成为衡量时代实力的核心标尺,更是穿越周期、引领变革的核心力量。2024 品牌智鉴榜,以 “智识为基、专业为刃、价值为魂”,历经百日全域筛查、多维体系核验、业界权威…

深入解析:MTK5G旗舰系列——天玑9500/9400/9300/9200/9000在AI和处理器性能、DDR频率及UFS的深度对比分析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

迈向人机共育的文明语法:AI元人文理论体系深度阐释——内观照叙事模型

迈向人机共育的文明语法:AI元人文理论体系深度阐释——内观照叙事模型 我们正站在一个文明史的奇点上。人工智能不再是遥远的科幻,而是深度介入社会运作、伦理决策与意义构建的“文明参与者”。传统的“价值对齐”范…

Day25综合案例一--CSS精灵--京东服务

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">…

Intellij扩展列表

开发idea插件,需要找到可用的扩展点,之前都是直接在网上搜索,最近详细看了下官方文档, 发现已经给我们列好了所有可用的扩展点 文档位置 https://plugins.jetbrains.com/docs/intellij/plugin-extensions.html#exp…

agentic terminal coding

opencode: https://github.com/sst/opencode The AI coding agent built for the terminalWhat is OpenCode? OpenCode is an open source agent that helps you write and run code directly from the terminal.[*] …

the badness of USA

it has no bad review. Maybe R/N/G can get the real worst some, but theres no even in the people they killed so much. so USA never changes. somehow.

Day3 Scrum冲刺博客

Day3 Scrum冲刺博客 1. 团队会议 todo补充会议照片 1)昨天已完成的工作前端实现个人设置弹窗以及问答模式静态页面,实现问答模式缓存 "关于我们"细节修正后端完成爬虫数据的数据清洗 增加爬虫程序适配的信…

完整教程:内核里常用宏BUG_ON/WARN_ON/WARN_ONCE

完整教程:内核里常用宏BUG_ON/WARN_ON/WARN_ONCE2025-11-26 22:27 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displa…

贪心专题笔记(从b站左程云老师那上完后的笔记)

https://www.bilibili.com/video/BV1ST4y1s7XT/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=56781f0f92104550238c449cb1aebd72 关键:用对数器验证 1.如果要排序,保证排序具有…

Agent编写全攻略(超详细)从零基础到精通,一篇搞定,不看后悔,赶紧收藏!

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …