(C/C++学习笔记) 十六. 预处理
十六. 预处理
● 关键字typeof
作用: 为一个已有的数据类型起一个或多个别名(alias), 从而增加了代码的可读性. typedef known_type_name new_type_name1, new_type_name2... 例如: typedef double Area, Volume; //double类型有Area和Volume两个别名 typedef int integer; integer a, b; //就相当于int a, b; |
#include <iostream.h> typedef char * String; //一般将typeof语句置于声明区, 头文件声明和宏定义之后; 为字符型指针起一个别名, 即String void main() { String str; char temp[]="Hello World"; str=temp; cout << str << endl; } |
|
● typedef后接两个别名
typedef char *PCHAR,*PSTR; //给char*取了两个新名字:一个叫PCHAR,另一个叫PSTR。 typedef char *PCHAR,PSTR; //给char*取个新名字叫PCHAR,给char取新名字叫PSTR。 |
● 预编译=预处理
预编译=预处理Precompiling=Preprocessing 预处理包括: ① 宏定义(上文已讲述); ② 文件包含; ③ 条件编译 |
● 文件包含
header file: 头文件, 可能翻译成"标题文件"更好 如果include包含的头文件在C/C++库函数中,那么就用#include < >, 如果包含的文件在当前目录下,那么用#inlclude " "。 |
//file1.h #define AAA 2 const int a = 3; //file2.c #include <stdio.h> #include "file1.h" void print_OK(int a) { printf("OK, %d\n", a); } int main(void) { #if AAA //如果AAA宏定义的值为真(即非0) print_OK(a); #endif return 0; //结束一个#if……#else条件编译块 } //文件包含命令执行后, file1.c #include <stdio.h> #define AAA 2 const int a = 3; void print_OK(int a) { printf("OK, %d\n", a); } int main(void) { #if AAA //如果AAA宏定义的值为真(即非0) print_OK(a); #endif return 0; //结束一个#if……#else条件编译块 } |
● 一般将如下内容放到.h文件中: ① 宏定义; ② 结构体, 联合体和枚举声明 ③ typedef声明
※ 在需要调用函数的文件中,用extern对函数声明,表示该函数是在其他文件中定义的外部函数
|
● 条件编译(conditional compilation)
作用: 只对满足一定条件的代码进行编译, 使用条件编译可方便地处理程序的调试版本(Debug Version)和正式(发行)版本(Release Version), 同时增强程序的可移植性. |
||||||||||||||||||||
|
● ① #if 指令 #if directive, ② #else指令, ③ #elif指令
① #if 指令 #if directive, ② #else指令, ③ #elif指令 ※ define 标识符 字符串 |
① 简单形式: #if constant_expression block_statement; #endif 例如: 为真, 执行下面的语句, 0为假, 不执行下面的语句 printf("\nPerformance should be good." ); #endif ② 复杂形式: #if condition_1 statement_block_1; #elif condition_2 statement_block_2; ... #elif condition_n statement_block_n; #else default_statement_block; #endif |
//案例1: #include<stdio.h> #define NUM 50 main() { int i=0; #if NUM>50 /*判断NUM是否大于50*/ i++; #endif #if NUM==50 i=i+50; #endif #if NUM<50 i--; #endif printf("Now i is:%d\n",i); } |
//案例2: #include<stdio.h> #define NUM 50 main() { int i=0; #if NUM>50 i++; #else #if NUM<50 i--; #else i=i+50; #endif #endif //第一个#if和最后一个#endif搭配, 第二个#if和倒数第二个if搭配 printf("i is:%d\n",i); } |
//案例3: #include<stdio.h> #define NUM 50 main() { int i=0; #if NUM>50 i++; #elif NUM<50 i--; #else i=i+50; #endif printf("i is:%d\n",i); } |
● #ifdef指令, #ifndef指令
//#ifdef的使用: #ifdef macro_name block_statement_1; #endif //或者: #ifdef macro block_statement_1; #else block_statement_2; #endif //#ifndef的使用: #ifndef macro_name block_statement_1; #endif //或者: #ifndef macro block_statement_1; #else block_statement_2; #endif |
//案例: #include<stdio.h> #define STR "diligence is the parent of success\n" main() { #ifdef STR printf(STR); #else printf("idleness is the root of all evil\n"); #endif printf("\n"); #ifndef ABC printf("idleness is the root of all evil\n"); #else printf(STR); #endif } |
● #undef指令
作用: 将宏定义局限在仅需要它的代码中 |
#undef macro_name |
#define MAX_SIZE 100 char array[MAX_SIZE]; #undef MAX_SIZE |
● 预定义宏(predefined macros) / 预定义标识符(predefined identifiers)
__DATE__: 进行预处理的日期("Mmm dd yyyy"形式的字符串文字) __FILE__: 代表当前源代码文件名的字符串文字 __LINE__: 代表当前源代码中的行号的整数常量 __TIME__: 源文件编译时间,格式微"hh:mm:ss" __func__: 当前所在函数名(在有的编译器中是: __FUNC__或__FUNCTION__) |
#include <stdio.h> #include <stdlib.h> void why_me(); int main() { printf( "The file is %s.\n", __FILE__ ); printf( "The date is %s.\n", __DATE__ ); printf( "The time is %s.\n", __TIME__ ); printf( "This is line %d.\n", __LINE__ ); //printf( "This function is %s./n", __func__ ); VC++ 6.0不能识别__func__ why_me(); return 0; } void why_me() { //printf( "This function is %s/n", __func__ ); printf( "The file is %s.\n", __FILE__ ); printf( "This is line %d.\n", __LINE__ ); } |
|
●
#line指令
#include "iostream" #line 100 "test.cpp" //如果不指定文件, 就处理当前文件 行 int main(int argc, char* argv[]) { cout<<"__LINE__: "<<__LINE__<<endl; return 0; } |
|
● #error指令
#error [用户自定义的错误消息] //方括号"[]"代表用户自定义的错误消息, 可以省略不写 |
/* 检查编译此源文件的编译器是不是C++编译器 如果使用的是C语言编译器则执行#error命令 如果使用的是 C++ 编译器则跳过#error命令 */ #ifndef __cplusplus #error 亲,您当前使用的不是C++编译器噢! #endif #include <stdio.h> int main() { printf("Hello,World!"); return 0; } |
|
● #pragma指令
#pragma指令(预处理指令中最复杂的指令) 作用是设定编译器的状态, 或者提示编译器完成一些特定的动作 |
例如: ① 在开发C99时,用C9X代表C99。编译器可以使用下面的编译指示(pragma)来启用对C9X的支持: #pragma c9x on ② #pragma warning(disable: n) //作用是将某个警报置为失效 例如, Visual C++ 2012 使用了更加安全的 run-time library routines, 所以在VS 2012 中编译 C 语言项目,如果使用了 scanf 函数,编译时便会提示如下错误:error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 在声明区写上#pragma warning (disable : 4996)即可忽略编译的错误提示 |
● 如何避免头文件被重复包含?
一般情况下,我们都是把函数声明、类定义、 模板定义等写到一个头文件里, 需要时将相应的头文件用#include 包含到源文件( *.cpp 文件)里来。 但头文件中又允许包含其它的头文件,这样就难免发生某个头文件被重复地包含。 我们可以使用编译预处理命令避免这种情况的发生。 例如, 你想确保头文件 max.h 不会被重复包含,则你可以采取如下的形式: 第一条预处理命令是说,如果 MAXMIN_H 不为真,说明此文件没被包含过,此命令后面的源代码有效(相当于:'如果大门没关, 请您进来'); 第二条预处理命令把 MAXMIN_H 置为真(相当于请您把门锁插上,不让第二个人进来)。 最后一条预处理命令是为了标出接受上述处理的源程序的范围(相当于您已经走到了后门)。 |
(C/C++学习笔记) 十六. 预处理的更多相关文章
- python3.4学习笔记(十六) windows下面安装easy_install和pip教程
python3.4学习笔记(十六) windows下面安装easy_install和pip教程 easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安 ...
- JavaScript权威设计--CSS(简要学习笔记十六)
1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domai ...
- MySQL学习笔记十六:锁机制
1.数据库锁就是为了保证数据库数据的一致性在一个共享资源被并发访问时使得数据访问顺序化的机制.MySQL数据库的锁机制比较独特,支持不同的存储引擎使用不同的锁机制. 2.MySQL使用了三种类型的锁机 ...
- python 学习笔记十六 django深入学习一 路由系统,模板,admin,数据库操作
django 请求流程图 django 路由系统 在django中我们可以通过定义urls,让不同的url路由到不同的处理函数 from . import views urlpatterns = [ ...
- SharpGL学习笔记(十六) 多重纹理映射
多重纹理就把多张贴图隔和在一起.比如下面示例中,一个表现砖墙的纹理,配合一个表现聚光灯效果的灰度图,就形成了砖墙被一个聚光灯照亮的效果,这便是所谓的光照贴图技术. 多重纹理只在OpenGL扩展库中才提 ...
- yii2源码学习笔记(十六)
Module类的最后代码 /** * Registers sub-modules in the current module. * 注册子模块到当前模块 * Each sub-module shoul ...
- Swift学习笔记十六:协议
Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能. 协议可以被类.枚举.结构体实现.满足协议要求的类,枚举,结构体被称为协议的遵循者. 遵循者须要提供协议指定的成员,如属性,方法 ...
- PHP学习笔记十六【方法】
<?php //给一个函数传递基本数据类型 $a=90; $b=90.8; $c=true; $d="hello world"; function test1($a,$b,$ ...
- Java基础学习笔记十六 集合框架(二)
List List接口的特点: 它是一个元素存取有序的集合.例如,存元素的顺序是11.22.33.那么集合中,元素的存储就是按照11.22.33的顺序完成的. 它是一个带有索引的集合,通过索引就可以精 ...
随机推荐
- excel依赖的dll
依赖的先后顺序 stdole.dll office.dll Microsoft.Vbe.Interop.dll Microsoft.Office.Interop.Excel.dll Interop是i ...
- Avito Cool Challenge 2018
考挂了.. A - Definite Game 直接看代码吧. #include<cstdio> #include<cstring> #include<algorithm ...
- [Redis] - redis实战
Microsoft Windows [版本 10.0.17134.472] (c) Microsoft Corporation.保留所有权利. C:\Users\SeeClanUkyo>f: F ...
- hdoj-1005-Number Sequences
题目:Number Sequences 代码: #include<stdlib.h> #include<iostream> #include<cstdio> #in ...
- UVa 12186 工人的请愿书(树形DP)
https://vjudge.net/problem/UVA-12186 题意: 一个老板和n个员工组成树状结构,每个员工都有自己的唯一上司,老板的编号为0,员工1~n,工人们打算签署一个志愿书给老板 ...
- DDSM数据处理之PngWithOverlay 框出病灶区域
修改代码路径 若overlay是某一侧的标注. 文件夹里某一侧的png 应该有对应 某一侧的overlay 这样一一对应才可以使得代码运行. 否则需要手动删除没有overlay的png图片. 左侧没有 ...
- 转载:Nginx负载均衡的5种策略
nginx可以根据客户端IP进行负载均衡,在upstream里设置ip_hash,就可以针对同一个C类地址段中的客户端选择同一个后端服务器,除非那个后端服务器宕了才会换一个. nginx的upstre ...
- springboot全局配置文件可设置的属性
# =================================================================== # COMMON SPRING BOOT PROPERTIE ...
- YOLO V2论文理解
概述 YOLO(You Only Look Once: Unified, Real-Time Object Detection)从v1版本进化到了v2版本,作者在darknet主页先行一步放出源代码, ...
- Android JNI学习(三)——Java与Native相互调用
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...