十六. 预处理

● 关键字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声明

  1. 外部函数声明

※ 在需要调用函数的文件中,用extern对函数声明,表示该函数是在其他文件中定义的外部函数

  1. 全局变量声明

● 条件编译(conditional compilation)

作用: 只对满足一定条件的代码进行编译, 使用条件编译可方便地处理程序的调试版本(Debug Version)和正式(发行)版本(Release Version), 同时增强程序的可移植性.

#

空指令,无任何效果

#include

包含一个源代码文件

#define

定义宏

#undef

取消已定义的宏

#if

如果给定条件为真,则编译下面代码

#ifdef

如果宏已经定义,则编译下面代码

#ifndef

如果宏没有定义,则编译下面代码

#elif

如果前面的#if给定条件不为真,当前条件为真,则编译下面代码

#endif

结束一个#if……#else条件编译块

#error

停止编译并显示错误信息

● ① #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++学习笔记) 十六. 预处理的更多相关文章

  1. python3.4学习笔记(十六) windows下面安装easy_install和pip教程

    python3.4学习笔记(十六) windows下面安装easy_install和pip教程 easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安 ...

  2. JavaScript权威设计--CSS(简要学习笔记十六)

    1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domai ...

  3. MySQL学习笔记十六:锁机制

    1.数据库锁就是为了保证数据库数据的一致性在一个共享资源被并发访问时使得数据访问顺序化的机制.MySQL数据库的锁机制比较独特,支持不同的存储引擎使用不同的锁机制. 2.MySQL使用了三种类型的锁机 ...

  4. python 学习笔记十六 django深入学习一 路由系统,模板,admin,数据库操作

    django 请求流程图 django 路由系统 在django中我们可以通过定义urls,让不同的url路由到不同的处理函数 from . import views urlpatterns = [ ...

  5. SharpGL学习笔记(十六) 多重纹理映射

    多重纹理就把多张贴图隔和在一起.比如下面示例中,一个表现砖墙的纹理,配合一个表现聚光灯效果的灰度图,就形成了砖墙被一个聚光灯照亮的效果,这便是所谓的光照贴图技术. 多重纹理只在OpenGL扩展库中才提 ...

  6. yii2源码学习笔记(十六)

    Module类的最后代码 /** * Registers sub-modules in the current module. * 注册子模块到当前模块 * Each sub-module shoul ...

  7. Swift学习笔记十六:协议

    Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能. 协议可以被类.枚举.结构体实现.满足协议要求的类,枚举,结构体被称为协议的遵循者. 遵循者须要提供协议指定的成员,如属性,方法 ...

  8. PHP学习笔记十六【方法】

    <?php //给一个函数传递基本数据类型 $a=90; $b=90.8; $c=true; $d="hello world"; function test1($a,$b,$ ...

  9. Java基础学习笔记十六 集合框架(二)

    List List接口的特点: 它是一个元素存取有序的集合.例如,存元素的顺序是11.22.33.那么集合中,元素的存储就是按照11.22.33的顺序完成的. 它是一个带有索引的集合,通过索引就可以精 ...

随机推荐

  1. ISSCC 2017论文导读 Session 14:ENVISION: A 0.26-to-10 TOPS/W Subword-Parallel DVAFS CNN Processor in 28nm

    ENVISION: A 0.26-to-10 TOPS/W Subword-Parallel Dynamic-Voltage-Accuracy-Frequency-Scalable CNN Proce ...

  2. Unity 之 transform

    transform.Translate 1.function Translate (translation : Vector3, relativeTo : Space = Space.Self) : ...

  3. [SpringBoot] - 上线一份项目记录

    首先在服务器上运行war包. (新建项目) 其后,选择数据库,因为之前感觉mysql比较难安装,这次就再试一次,之前的PostgreSQL没有问题. 将原有文件进行复制,排除导包错误. 首先测试邮件发 ...

  4. echart折线图,柱状图,饼图设置颜色

    转载: 之前在做报表的时候用过echart 用完也就完了,而这次在用的时候已经忘了,所以这里简单记录一下,好记性不如烂笔头!!! 1.折线图修改颜色: xAxis: { type: 'category ...

  5. python 正则表达式替换字符串中匹配的字符

    import re street = '21 Ramkrishna Road' print(re.sub('Road$', 'Rd.', street)) 将结尾的Road用Rd.替换

  6. Beta冲刺三——《WAP团队》

    β冲刺第三天  1. 今日完成任务情况以及遇到的问题. ①马麒.杜有海:管理员审核表的进一步完善 ②郝明宇:登录.注册界面的完善 ③马宏伟.周欣:继续完善前端数据借用与后台的连接 ④乌勒扎:登录与注册 ...

  7. Unity另外一套简单日志控制系统

    using UnityEngine; public class LogPrintf { static LogLevel logLevel = LogLevel.LOG_LEVEL_ERROR; pub ...

  8. JS循环汇总

    JS循环汇总 一.总结 一句话总结:js中的循环主要有while.for.for...in.for...of,循环是,要区别不同的循环对象,比如对象,数组,集合等 while for for...in ...

  9. 在WinForm应用程序中嵌入WPF控件

    我们知道,在WPF界面上添加WinForm的控件需要使用WindowsFormHost类.而在WinForm界面上添加WPF控件该如何做呢?有没有类似的类呢?明显是有的,ElementHost就是为了 ...

  10. 011 - JDK自带的性能监控工具

      一.概要: jps -l 查看现有的java进程 jps -l 显示所有正在运行的java进程id   jstack 查看Java线程      jstack -l pid; 做thread du ...