1 章 预 处 理 器

预 处 理 器 是 一 种 处 理 源 文 件 文 本 的 文 本 处 理 器 , ±它 是 翻 译 起 始 阶 段 的 一 个 组 成部 分 。

预 处 理 器 并 不 在 语 法 上 分 析 处 理 源 文 本 , 但 出 于 定 位 宏 调 用 的 目 的 , 它 将 源 文 本分 开 语 言 符 号 。 虽 然 编 译 器 一 般 在 初 次 编 译 时 启 动 预 处 理 器 , 但 预 处 理 器 也 可 以不 经 编 译 , 单 独 地 处 理 文 本 。

Microsoft 特 殊 处 →

用 /E 或 /EP 编 译 器 选 项 进 行 预 处 理 之 后 , 你 可 以 得 到 一 个 源 代 码 的 列 表 。 在 多 数情 况 下 , 启 动 预 处 理 器 和 输 出 结 果 文 本 到 输 出 设 备 , 这 两 种 选 项 都 是 控 制 台 指 令 , 这 两 种 选 项 的 区 别 在 于 /E 包 括 了 #line 指 令 ,/EP 没 有 这 些 指 令 。

Microsoft 特 殊 处 结 束

特 殊 术 语

在 本 书 中 , 名词 “ 参 量 ” 指 的 是 传 送 给 一 个 函 数 的 实 体 。 有 时 候 , 它用 “ actual ” 或 “ formal ” 修 饰 , 它 们 分 别 用 于 表 示 函 数 调 用 时 的 参 量 表 达 式 和 在 函 数 定 义 时的 参 量 说 明 。 名 词 “ 变 量 ” 指 的 是 一 种 简 单 的 C 类 型 数 据 对 象 , 名 词 “ 对 象 ” 指的 是 C++ 对 象 和 变 量 ; 它 是 一 个 含 义 广 泛 的 名 词 。

翻 译 阶 段

C 和 C++ 程 序 由 一 个 或 多 个 源 文 件 组 成 , 它 们 都 包 含 了 程 序 的 某 些 文 本 , 一 个 不 包含 代 码 部 分 的 源 文 件 和 它 的 包 含 文 件 ( 用 #indude 预 处 理 器 指 令 包 含 的 文 件 ), 若被 条 件 编 译 指 令 ( 比 如 #if) 调用 , 则 称 其 为 一 个 “ 转 换 单 元 ”。

源 文 件 可 被 翻 译 多 次 , 翻 译 过 去 的 文 件 事 实 上 是 很 正 常 的 。 已 经 翻 译 了 的 翻 译 单元 可 保 存 在 单 独 的 对 象 文 件 或 对 象 代 码 库 里 , 这 些 单 个 的 转 换 单 元 可 被 连 接 形 成一 个 可 执 行 文 件 或 动 态 链 接 库 (DLL) 。

转 换 单 元 可 采 用 下 列 形 式 通 信 :

  • 调 用 具 有 外 部 连 接 的 函 数 。

  • 调 用 具 有 外 部 连 接 的 类 成 员 函 数 。

  • 直 接 更 改 具 有 外 部 连 接 的 对 象 。

  • 文 件 的 直 接 更 改 。

  • 内 部 外 理 通 信 ( 仅 限 于 基 于 Microsoft Windows 的 应 用 程 序 ) 。以 下 是 编 译 器 翻 译 文 件 的 各 个 阶 段 :

字 符 映 射

源 文 件 中 的 字 符 被 映 射 为 内 部 源 代 码 的 形 式 。 ±此 阶 段 三 字 母 序 列 被 转 换 为 单 字符 的 内 部 表 现 形 式 。

行 拼 接

在 此 阶 段 , 源 文 件 中 所 有 以 反 斜 杠 (\) 结 尾 且 其 后 紧 跟 一 换 行 符 的 行 , ±将 与 下 一行 连 接 , 从 而 由 物 理 行 生 成 逻 辑 行 。 所 有 非 空 源 文 件 结 束 于 一 个 前 面 没 有 反 斜 杠的 换 行 符 。

语 言 符 号 化

此 阶 段 源 文 件 被 分 为 预 处 理 语 言 符 号 和 空 白 字 符 。 源 文 件 中 每 个 注 释 被 用 一 个空 白 字 符 代 替 。 换 行 符 被 保 留 。

预 处 理

此 阶 段 执 行 预 处 理 指 令 并 将 宏 扩 展 至 源 文 件 ,#include 语 句 调 用 对 所 有 包 括 文本 启 动 前 面 三 个 翻 译 步 骤 开 头 的 翻 译 过 程 。

字 符 集 映 射

所 有 的 源 字 符 集 成 员 和 转 义 序 列 将 转 换 为 执 行 字 符 集 中 的 等 价 形 式 , 对 于Microsoft C 和 C++ 来 说 , 源 字 符 集 和 执 行 字 符 集 都 是 ASCII 码。

字 符 串 合 并

所 有 相 邻 的 字 符 串 和 宽 字 符 文 字 都 将 被 合 并 。 例 如 :“ String ”“ concatenation ”合 并 为 “ String concatenation ”。

翻 译

所 有 的 语 言 符 号 将 按 语 法 和 语 义 规 则 进 行 分 析 ; 这 些 语 言 符 号 被 转 换 为 目 标 代码 。

链 接

此 阶 段 所 有 的 外 部 引 用 被 分 解 以 生 成 一 个 可 执 行 程 序 或 一 个 动 态 链 接 库 。编 译 器 在 翻 译 过 程 中 遇 到 语 法 错 误 时 , 将 发 出 一 个 警 告 或 错 误 信 息 。

链 接 器 分 解 所 有 的 外 部 引 用 , 并 把 一 个 或 多 个 分 开 处 理 的 转 换 单 元 和 标 准 库 联 接起 来 , 以 生 成 一 个 可 执 行 程 序 或 动 态 链 接 库 (DLL) 。

预 处 理 器 指 令

预 处 理 器 指 令 如 #define 和 #ifdef, ±一 般 被 用 在 不 同 的 运 行 环 境 下 , 使 源 程 序易 于 更 改 和 编 译 。 源 文 件 中 的 指 令 指 示 预 处 理 器 执 行 特 有 的 行 为 。 例 如 , 预 处 理器 可 替 换 文 本 中 的 语 言 符 号 , 将 其 它 的 文 件 内 容 插 入 源 文 件 中 , 或 移 走 文 本 的 一部 分 以 抑 制 文 件 中 某 部 分 的 编 译 。 预 处 理 器 行 在 宏 扩 展 之 前 被 识 别 且 执 行 。 不过 , 如 果 宏 扩 展 看 起 来 象 一 个 预 处 理 器 指 令 , 该 命 令 将 不 能 被 预 处 理 器 识 别 。

除 转 义 序 列 之 外 , 预 处 理 器 语 句 采 用 与 源 文 件 语 句 相 同 的 字 符 集 。 在 预 处 理 器 语句 中 的 字 符 集 和 可 执 行 程 序 的 字 符 集 是 一 样 的 。 预 处 理 器 也 可 识 别 负 字 符 值 。预 处 理 器 可 识 别 如 下 指 令 :

#define #error #import #undef #elif #if #include

#else #ifdef #line

#endif #ifndef #pragma

数 字 符 号 (#) 是 包 含 预 处 理 器 指 令 的 行 中 的 第 一 个 非 空 白 字 符 。 ±空 白 字 符 可 出现 在 数 字 符 号 和 指 令 的 第 一 个 字 母 之 间 。 某 些 指 令 包 含 参 量 和 值 。 指 令 之 后 的任 何 文 本 ( 除 作 为 指 令 一 部 分 的 参 量 或 值 之 外 ) 必 须 放 在 单 行 注 释 分 界 符 (//) 之后 或 注 释 分 界 符 (/* */) 之 间 。

预 处 理 器 指 令 可 出 现 在 源 文 件 的 任 何 地 方 , 但 它 们 仅 用 于 源 文 件 的 剩 余 部 分 。

#define 指 令

可 以 用 #define 指 令 给 程 序 中 的 常 量 取 一 个 有 意 义 的 名 称 , 其 语 法 的 两 种 形 式 如下 :

语 法

#define 标 识 符 语 言 符 号 字 符 串 opt

#define 标 识 符 [( 标 识 符 opt ,..., 标 识 符 opt )] ±语 言 符 号 字 符 串 opt

#define 指 令 用 语 言 符 号 字 符 串 替 换 源 文 件 中 一 个 标 识 符 的 所 有 出 现 , 标 识 符 仅在 它 形 成 一 个 语 言 符 号 时 被 替 换 ( 参 见 “ Microsoft Visual C++ 6.0 ±参 考 库 ” 的 “ Microsoft Visual C++ 6.0 ±语 言 参 考 手 册 ” 卷 的 第 1 章 “ 词 法 规 定 ” 中 的“ 语 言 符 号 ” ) 。 例 如 , ±若 标 识 符 出 现 在 一 个 注 释 、 一 个 字 符 串 或 作 为 一 个 长 标识 符 的 一 部 分 之 中 , 它 就 不 被 替 换 。

  • 个 不 带 语 言 符 号 字 符 串 的 #define 指 令 将 移 走 源 文 件 中 每 次 标 识 符 的 出 现 。标 识 符 保 留 其 定 义 且 能 用 #defined 和 #ifdef 测 试 。

语 言 符 号 字 符 串 参 量 由 一 系 列 语 言 符 号 组 成 , 如 关 键 字 、 常 量 或 完 整 的 语 句 。 一个 或 多 个 空 白 字 符 可 将 语 言 符 号 字 符 串 和 标 识 符 分 开 。 空 白 字 符 不 会 被 认 为 是被 替 换 文 本 的 一 部 分 , 文 本 最 后 语 言 符 号 之 后 的 空 白 也 不 会 认 为 是 替 换 文 本 的 一部 分 。

形 式 参 数 名 称 出 现 在 语 言 符 号 字 符 串 中 以 标 志 出 实 际 值 被 替 换 的 位 置 , ±每 个 参数 名 称 可 在 语 言 符 号 字 符 串 中 出 现 多 次 , 且 可 以 以 任 何 次 序 出 现 。 调 用 时 参 量 的数 目 必 须 与 宏 定 义 的 参 数 数 目 相 匹 配 。 圆 括 号 的 自 由 运 用 可 确 保 正 确 地 说 明 复杂 的 实 际 参 量 。

用 第 二 种 语 法 形 式 可 创 建 类 似 函 数 的 宏 。 这 种 形 式 接 受 一 个 用 圆 括 号 括 起 的 可选 参 数 表 。 在 最 初 定 义 之 后 引 用 该 标 识 符 , 可 以 使 用 实 际 参 量 替 代 形 式 参 数 的 语言 符 号 字 符 串 参 量 的 形 式 , 来 替 换 标 识 符 ( 标 识 符 opt ,..., 标 识 符 opt ) 的 每 次 出现 。

表 中 的 形 式 参 数 必 须 用 逗 号 隔 开 。 该 表 中 的 每 个 名 称 都 必 须 是 唯 一 的 , 且 此 参 量表 必 须 包 括 在 圆 括 号 中 , 标 识 符 和 左 边 的 圆 括 号 之 间 不 能 有 空 格 。 对 于 占 用 多 行的 长 指 令 可 使 用 行 连 接 , 把 反 斜 杠 (\) 放 在 换 行 符 前 。 ±形 式 参 数 名 称 的 范 围 延 伸到 结 束 语 言 符 号 字 符 串 的 换 行 符 。

当 一 个 宏 以 第 二 种 语 法 形 式 定 义 时 , 参 量 表 后 的 文 本 实 例 就 构 成 一 个 宏 调 用 。 在源 文 件 中 , 一 个 标 识 符 实 例 后 的 实 际 参 量 必 须 与 宏 定 义 的 相 应 形 式 参 数 匹 配 。每 个 语 言 符 号 字 符 串 之 前 无 字 符 串 化 (#) 、 字 符 化 (#@) 或 语 言 符 号 粘 贴 (##) 操 作符 , 或 其 后 无 ## 操 作 符 的 形 式 参 量 , 都 被 相 应 的 实 际 参 量 所 替 换 。 在 指 令 替 换 形式 参 数 之 前 , 实 际 参 量 中 的 任 何 宏 都 将 被 扩 展 ( 本 章 之 后 的 “ 预 处 理 器 操 作 符 ” 中 将 介 绍 这 些 操 作 符 ) 。

以 下 带 参 量 宏 的 例 子 说 明 了 #define 语 法 的 第 二 种 形 式 :

// 定 义 光 标 行 的 宏

# define CURSOR(top,bottom) ((top) << 8) | bottom) )

// 获 取 指 定 范 围 中 的 一 个 随 机 整 数 的 宏# define getrandom(min,max) \

(( rand()%(int)(((max)+1)-(min)))+(min))

有 副 作 用 的 参 量 有 时 会 导 致 宏 产 生 不 希 望 的 结 果 。 一 个 给 定 的 形 式 参 量 在 语 言

符 号 字 符 串 中 可 能 出 现 多 次 。 如 果 该 形 式 参 数 被 一 个 有 副 作 用 的 表 达 式 所 替 换 , 则 该 表 达 式 及 其 副 作 用 , 可 能 被 求 值 多 次 ( 参 见 本 章 后 面 “ 语 言 符 号 粘 贴 操 作 符## ” 中 的 例 子 ) 。

#undef 指 令 可 使 一 个 标 识 符 的 预 处 理 器 定 义 失 效 。 有 关 的 更 多 信 息 参 见 #undef 指 令 。 若 一 个 被 定 义 的 宏 名 称 出 现 在 语 言 符 号 字 符 串 中 ( 即 使 是 另 一 个 宏 扩 展 的结 果 ), 它 将 不 被 扩 展 。

除 非 第 二 次 定 义 ( #define ) 宏 与 原 定 义 完 全 相 同 , 否 则 重 定 义 一 个 已 定 义 过 的宏 将 产 生 一 个 错 误 信 息 。

Microsoft 特 殊 处 →

Microsoft C/C++ 允 许 一 个 宏 的 重 定 义 , 但 会 产 生 一 个 警 告 信 息 , 说 明 新 的 定 义 与原 定 义 相 同 。 ANSI C 认 为 宏 的 重 定 义 是 错 误 的 。 例 如 , 下 面 的 宏 对 C/C++ 是 相 同的 , 但 会 产 生 一 个 警 告 信 息 :

# define test(f1,f2) (f1*f2) # define test(a1,a2) (a1*a2)

Microsoft 特 殊 处 结 束

这 个 例 子 用 于 说 明 #define 指 令 :

# define WIDTH 80

# define LENGTH (WIDTH+10)

第 一 个 说 明 定 义 标 识 符 WIDTH 为 整 形 常 量 80, 且 用 WIDTH 和 整 形 常 量 10 定 义LENGTH 。 LENGTH 的 每 次 出 现 都 用 (WIDTH+10) 所 替 换 , 接着 ,WIDTH+10 的 每 次 出 现都 用 表 达 式 (80+10) 替 换 。 WIDTH+10 的 圆 括 号 非 常 重 要 , 因 为 它 们 决 定 着 如 下 语句 的 解 释 。

var=LENGTH*20 ;

经 预 处 理 后 该 语 句 变 为 :

var=(80+10)*20 ;

求 得 值 为 1800, 若 无 括 号 , 结 果 为 :

var=80+10*20 其 值 为 280 。

Microsoft 特 殊 处 →

在 文 件 开 头 用 /D 编 译 器 选 项 定 义 宏 和 常 量 , 和 用 一 个 #define 预 处 理 指 令 效 果 是一 样 的 。 能 用 /D 选 项 定 义 的 宏 可 达 30 个 。

Microsoft 特 殊 处 结 束#error 指 令

采 用 error 指 令 可 产 生 编 译 错 误 信 息 。

语 法

#error 语 言 符 号 字 符 串

错 误 消 息 包 括 语 言 符 号 字 符 串 参 量 , 且 从 属 于 宏 扩 展 。 这 些 指 令 对 于 检 测 程 序 的前 后 矛 盾 和 预 处 理 时 的 违 犯 约 束 是 非 常 有 用 的 , 以 下 例 子 说 明 了 预 处 理 时 的 出 错处 理 :

# if !defined( __ cplusplus)

# error C++ complier required. # endif

当 遇 到 #error 指 令 时 , 编 译 终 止 。

#if , #elif , #else 和 #endif 指 令

#if 、#elif 、#else 和 #endif 指 令 控 制 源 文 件 中 某 部 分 的 编 译 。 如 果 表 达 式 (#if 之 后 ) 有 一 个 非 0 值 , 则 紧 跟 在 #if 指 令 之 后 的 行 组 将 保 留 在 转 换 单 元 中 。

语 法

条 件 的 :

if 部 分 elif 部 分 opt else 部 分 opt endif 行if 部 分 :

if 行 文 本if 行 :

#if 常 量 表 达 式

#ifdef 标 识 符

#ifndef 标 识 符elif 部 分 :

elif 行 文 本

elif 部分 elif 行 文 本elif 行 :

#elif 常 量 表 达 式else 部 分 :

else 行 文 本else 行 :

# else

endif 行 :

# endif

源 文 件 中 每 个 #if 指 令 都 必 须 与 最 近 的 一 个 #endif 相 匹 配 。 在 #if 和 #endif 指令 之 前 的 #elif 指 令 的 数 目 是 不 限 的 , 但 最 多 只 能 有 一 个 #else 指 令 。 #else 必须 是 #endif 之 前 的 最 后 一 个 指 令 。

#if 、 #elif 、 #else 和 #endif 指 令 可 嵌 套 在 其 它 #if 指 令 的 文 本 部 分 。 每 个 嵌套 的 #else 、 #elif 或 #endif 指 令 应 属 于 前 面 最 近 的 一 个 #if 指 令 。

所 有 的 条 件 编 译 指 令 , 如 #if 和 #ifdef, 必 须 与 文 件 结 束 前 最 近 的 #endif 指 令 匹配 ; 否 则 , 将 产 生 一 个 错 误 消 息 。 当 条 件 编 译 指 令 包 括 在 包 含 文 件 中 时 , 他 们 必 须满 足 相 同 的 条 件 : 在 包 含 文 件 结 尾 没 有 不 匹 配 的 条 件 编 译 指 令 。

宏 替 换 应 在 #elif 命 令 后 的 命 令 行 部 分 内 进 行 , 因 此 一 个 宏 调 用 可 用 在 常 量 表 达式 中 。

预 处 理 器 选 择 一 个 给 定 文 本 的 出 现 之 一 作 进 一 步 的 处 理 。 文 本 中 指 定 的 一 个 块可 以 是 文 本 的 任 何 序 列 。 它 可 能 占 用 一 行 以 上 。 通 常 该 文 本 是 对 于 编 译 和 预 处理 器 有 意 义 的 程 序 文 本 。

预 处 理 器 处 理 选 择 文 本 并 将 其 传 送 给 编 译 器 。 若 该 文 本 包 含 预 处 理 器 指 令 , 预 处理 器 将 执 行 这 些 指 令 。 编 译 器 只 编 译 预 处 理 器 选 定 的 文 本 块 。

预 处 理 器 通 过 求 值 每 个 #if 或 #elif 指 令 之 后 的 常 量 表 达 式 直 到 找 到 一 个 为 真( 非 0) 的 常 量 表 达 式 来 选 择 单 个 文 本 项 。 预 处 理 器 选 择 所 有 的 文 本 ( 包 括 以 # 开头 的 其 它 预 处 理 器 指 令 ) 直 到 它 关 联 的 #elif 、 #else 或 #endif 。

如 果 常 量 表 达 式 的 所 有 出 现 都 为 假 , 或 者 如 果 没 有 #elif 指 令 , 预 处 理 器 将 选 择#else 后 的 文 本 块 。 如 果 #else 被 忽 略 , 且 所 有 #if 块 中 的 常 量 表 达 式 都 为 假 ,

则 不 选 择 任 何 文 本 块 。

常 量 表 达 式 是 一 个 有 以 下 额 外 限 制 的 整 型 常 量 表 达 式 :

  • 表 达 式 必 须 是 整 型 且 可 以 包 括 整 型 常 量 , 字 符 常 量 和 defined 操 作符 。

  • 表 达 式 不 能 使 用 sizeof 或 一 个 类 型 造 型 操 作 符 。

  • 目 标 环 境 不 能 表 示 整 数 的 所 有 范 围 。

  • 在 翻 译 表 示 中 ,int 类 型 和 long 类 型 以 及 unsigned int 类 型 和unsigned long 类 型 是 相 同 的 。

  • 翻 译 器 可 将 字 符 常 量 翻 译 成 一 组 不 同 于 目 标 环 境 的 代 码 值 。 为 了 确定 目 标 环 境 的 属 性 , 应 在 为 目 标 环 境 建 立 的 应 用 程 序 中 检 测LIMITS.H 的 宏 值 。

  • 表 达 式 不 需 执 行 所 有 的 环 境 查 询 , 但 需 与 目 标 计 算 机 的 执 行 过 程 细节 隔 离 开 。

预 处 理 器 操 作 符 defined 可 用 于 特 殊 的 常 量 表 达 式 , 语 法 如 下 :

语 法

defined( 标 识 符 ) defined 标 识 符

若 此 标 识 符 当 前 已 定 义 , 则 该 常 量 表 达 式 被 认 为 是 真 ( 非 0); 否 则 , 条 件 为 假 (0) 。一 个 定 义 为 空 文 本 的 标 识 符 可 认 为 已 定 义 。 defined 指 令 只 能 用 于 #if 和 #endif 指 令 。

在 如 下 例 子 中 ,#if 和 #endif 指 令 控 制 着 三 个 函 数 调 用 中 某 一 个 的 编 译 : # if defined (CREDIT)

credit();

# elif defined(DEBIT)

debit(); # else

printerror(); # endif

若 标 识 符 CREDIT 已 定 义 , 则 对 于 credit 的 函 数 调 用 被 编 译 。 若 标 识 符 DEBIT 被定 义 , 则 对 于 debit 的 函 数 调 用 被 编 译 。 若 未 定 义 任 何 标 识 符 , ±将 编 译 对 于printerror 的 函 数 调 用 。

注 意 , 在 C 和 C++ 中 ,CREDIT 和 credit 是 不 同 的 标 识 符 , 因 为 它 们 的 大 小 写 不 一样 。

如 下 例 子 中 的 条 件 编 译 语 句 给 出 了 一 个 名 称 为 DLEVEL 的 已 定 义 的 符 号 常 量 : # if DLEVEL > 5

# define SIGNAL 1

# if STACKUSE == 1

# define STACK 200

# else

# define STACK 100

# endif # else

# define SIGNAL 0

# if STACKUSE==1

# define STACK 100

# else

# define STACK 50 # endif

# endif

# if DLEVEL==0

# define STACK 0 # elif DLEVEL==1

# define STACK 100 # elif DLEVEL > 5

display(debugptr); # else

# define STACK 200 # endif

第 一 个 #if 块 中 有 两 组 嵌 套 的 #if 、 #else 和 #endif 指 令 。 第 一 组 指 令 仅 当DLEVELl>5 为 真 时 执 行 ; 否 则 , 执 行 #else 之 后 的 语 句 。

第 二 组 中 的 #elif 和 #else 指 令 选 择 基 于 DLEVEL 值 的 四 个 选 项 之 一 。 常 量 STACK 依 据 DLEVEL 定 义 为 0 , 100 或 200 。 若 DLEVEL 大 于 5, 则 编 译 语 句 :

# elif DLEVEL > 5 display(debugptr); 且 此 时 不 定 义 STACK 。

条 件 编 译 一 般 用 于 防 止 同 一 头 文 件 的 多 重 包 含 。 C++ ±中 在 头 文 件 内 经 常 定 义 类

的 位 置 , 可 使 用 如 下 结 构 来 防 止 多 次 定 义 。

//EXAMPLE.H 例 子 头 文 件

# if !defined(EXAMPLE_H) # define E xample E_H

class E xample

{

...

};

# endif //!defined(EXAMPLE_H)

上 面 的 代 码 用 于 检 查 符 号 常 量 EXAMPLE_H 是 否 已 定 义 。 若 已 定 义 , 该 文 件 就 已 被包 括 且 不 需 再 处 理 ; 如 果 未 定 义 , 常 量 EXAMPLE_H 将 被 定 义 , 以 标 记 EXAMPLE.H 为已 经 处 理 。

Microsoft 特 殊 处 →

条 件 编 译 表 达 式 被 看 作 为 signed long 值 , 且 这 些 表 达 式 与 C++ 中 的 表 达 式 采 用相 同 的 规 则 求 值 。 例 如 , 表 达 式 :

# if 0xFFFFFFFFL > 1UL

为 真 。

Microsoft 特 殊 处 结 束

#ifdef 和 ifndef 指 令

#ifdef 和 #ifndef 指 令 与 使 用 defined( 标 识 符 ) 操 作 符 的 作 用 是 一 样 的 。

语 法

#ifdef 标 识 符#ifndef 标 识 符等 同 于

#if defined 标 识 符# if !defined 标 识 符

#if 指 令 能 用 的 任 何 地 方 都 可 以 用 #ifdef 和 #ifndef 指 令 。 当 标 识 符 已 被 定 义时 ,#ifdef 标 识 符 语 句 等 同 于 #if 1; 而 当 标 识 符 未 定 义 或 用 #undef 指 令 对 其 反定 义 时 , 该 语 句 等 同 于 #if 0 。 这 些 指 令 仅 用 于 检 查 C 或 C++ 源 代 码 中 是 否 出 现该 标 识 符 , 而 不 是 用 于 检 查 C 或 C++ 源 程 序 中 该 标 识 符 的 说 明 。

提 供 这 几 个 指 令 只 为 了 与 该 语 言 的 老 版 本 兼 容 。 目 前 的 趋 势 是 偏 向 于 采 用defined( 标 识 符 ) 定 义 常 量 表 达 式 的 #if 指 令 。

#ifndef 指 令 测 试 与 #ifdef 相 反 的 条 件 。 若 标 识 符 未 定 义 ( 或 已 用 #undef 反 定义 ), 其 条 件 为 真 ( 非 0); 反 之 , 条 件 为 假 (0) 。

Microsoft 特 殊 处 →

可 以 使 用 /D 选 项 从 命 令 行 传 送 标 识 符 , 采 用 /D 选 项 至 多 可 以 指 定 30 个 宏 。检 查 一 个 定 义 是 否 存 在 是 非 常 有 用 的 , 因 为 定 义 可 从 命 令 行 传 送 。 例 如 :

//prog.cpp

#ifndef test // 这 三 个 语 句 放 在 你 的 代 码 中

# define final # endif

CL /Dtest prog.cpp // 这 是 编 译 的 命 令

Microsoft 特 殊 处 结 束#import 指 令

C++ 特 殊 处 →

#import 指 令 用 于 从 一 个 类 型 库 中 结 合 信 息 。 该 类 型 库 的 内 容 被 转 换 为 C++ 类 , 主 要 用 于 描 述 COM 界 面 。

语 法

#import " 文 件 名 " [ 属 性 ] #import < 文 件 名 > [ 属 性 ] 属 性 :

属 性 1, 属性 2,...

属 性 1 属 性 2 ...

文 件 名 是 一 个 包 含 类 型 库 信 息 的 文 件 的 名 称 。 一 个 文 件 可 为 如 下 类 型 之 一 :

  • 一 个 类 型 库 (.TLB 或 .ODL) 文 件 。

  • 一 个 可 执 行 (.EXE) 文 件 。

  • 一 个 包 含 类 型 库 资 源 ( 如 .OCX) 的 库 文 件 (.DLL) 。

  • 一 个 包 含 类 型 库 的 复 合 文 档 。

  • 其 它 可 被 LoadTypeLib API 支 持 的 文 件 格 式 。

文 件 名 之 前 可 以 有 一 个 目 录 规 格 。 文 件 名 必 须 是 一 个 已 存 在 文 件 的 名 称 。 ±两 种格 式 的 区 别 是 当 路 径 未 完 全 说 明 时 , 预 处 理 器 检 索 类 型 库 文 件 的 顺 序 不 同 。

动作

语法格 式

引号格式 这 种 格 式 让 预 处 理 器 首 先 搜 索 与 包 含 #import 语 句 的 文 件同 一 目 录 的 类 型 库 文 件 , 然 后 在 所 有 包 括 (#include) 该 文件的目录中搜索 , 最后在如下路径中搜索

尖括号格式 这种格式指示预处理器沿以下路径搜索类型库文件

编 译 器 在 以 下 目 录 中 搜 索 已 命 名 的 文 件 :

  1. PATH 环 境 变 量 路 径 表 。

  2. LIB 环 境 变 量 路 径 表 。

  3. 用 / I( 额 外 的 包 括 目 录 ) 编 译 器 选 项 指 定 的 路 径 。

#import 可 以 任 选 地 包 含 一 个 或 多 个 属 性 。 这 些 属 性 使 编 译 器 改 变 类 型 库 头 文件 的 内 容 。 一 个 反 斜 杠 (\) 符 可 用 在 一 个 单 一 的 #import 语 句 中 包 含 额 外 的 行 , 例 如 :

# import "test.lib" no_namespace \

rename("OldName","NewName") #import 属 性 列 出 如 下 :

exclude high_method_prefix high_property_prefixes implementation_only include(...) inject_statement

named_guids no_auto_exclude

续 表

no_implementation no_namespace raw_dispinterfaces raw_interfaces_only raw_method_prefix raw_native_types raw_property_prefixes rename rename_namespace

#import 指 令 可 创 建 两 个 在 C++ 源 代 码 中 重 构 类 型 库 内 容 的 头 文 件 , 第 一 个 头 文件 和 用 Microsoft 接 口 定 义 语 言 (MIDL) 编 译 器 生 成 的 头 文 件 类 似 , 但 有 额 外 的 编译 器 生 成 代 码 和 数 据 。 第 一 个 头 文 件 与 类 型 库 有 相 同 的 基 本 名 , 其 扩 展 名为 .TLH 。 第 二 个 头 文 件 也 有 与 类 型 库 相 同 的 基 本 名 , 其 扩 展 名 为 .TLI 。 它 包 括 了编 译 器 生 成 成 员 函 数 的 实 现 , 且 被 包 含 在 (#include) 的 第 一 个 头 文 件 内 。

两 个 头 文 件 都 在 用 /Fo( 命 名 对 象 文 件 ) 选 项 指 定 的 输 出 目 录 中 。 随 后 它 们 被 读 出和 编 译 , 就 像 第 一 个 头 文 件 被 #include 指 令 命 名 一 样 。

以 下 是 伴 随 #import 指 令 的 编 译 器 优 化 :

  • 头 文 件 被 创 建 时 , 将 被 分 配 与 类 库 相 同 的 时 间 标 志 。

  • 处 理 #import 时 , 编 译 器 首 先 测 试 头 文 件 是 否 存 在 , 是 否 过 期 。 若 条件 为 真 , 就 不 需 重 新 创 建 。

  • 编 译 器 延 迟 对 于 OLE 子 系 统 的 初 始 化 , 直 到 碰 到 第 一 个 #import 命令 。

#import 指 令 也 可 参 与 最 小 重 建 且 可 被 置 于 一 个 预 编 译 头 文 件 中 。

基 本 类 型 库 头 文 件

基 本 类 型 库 头 文 件 由 七 个 部 分 组 成 :

  1. 头 部 固 定 正 文 : 由 注 释 、 COMDEF.H( 定 义 用 在 头 部 的 一 些 标 准 宏 ) 的 #include 语 句 和 其 它 繁 杂 的 安 装 信 息 组 成 。

  2. 前 向 引 用 和 类 型 定 义 : 由 象 struct IMyinterface 之 类 的 结 构 说 明 和 用 于 一 些TKIND_ALIAS 项 的 类 型 定 义 组 成 。

  3. 灵 敏 指 针 说 明 : 模 块 类 _com_ptr_t 是 一 个 封 装 接 口 指 针 和 消 除 调 用 AddRef 、Release 和 QueryInterface 函 数 需 求 的 灵 敏 指 针 实 现 。 此 外 , 它 隐 藏 了 创 建 一个 新 COM 对 象 中 的 CoCreateInstance 调 用 。 此 部 分 采 用 宏 语 句

_COM_SMARTPTR_TYPEDEF 将 COM 接 口 的 类 型 定 义 创 建 为 _com_ptr_t 模 板 类 的 模板 特 例 化 。 例 如 , 对 于 界 面 IFoo,.TLH 文 件 包 含 有 :

_ COM _ SMARTPTR _ TYPEDEF(IFoo, _ _ uuidof(IFoo)); 编 译 器 将 其 扩 展 为 :

type def _com_ptr_t<_com_IIID<IFoo,_ _uuidof(IFoo) >> IFooPtr;

类 型 IFooPtr 可 以 用 在 原 始 的 界 面 指 针 IFoo* 的 地 方 。 结 果 , 就 不 需 调 用 各 种IUnknown 成 员 函 数 。

  1. 类 型 信 息 ( typeinfo) 说 明 : 主 要 由 类 定 义 和 其 它 项 组 成 , 这 些 项 说 明 由ITyptLib:GetTypeInfo 返 回 的 单 个 的 信 息 类 型 项 目 。 在 这 部 分 , 每 个 来 自 于 类型 库 的 信 息 类 型 都 以 一 种 依 赖 于 TYPEKIND 信 息 的 格 式 反 映 在 该 头 部 。

  2. 任 选 旧 式 GUID 定 义 : 包 含 命 名 的 GUID 常 量 的 初 始 化 过 程 , 这 些 定 义 是 格 式CLSID_CoClass 和 IID_Interface 的 名 称 , 与 那 些 由 MIDL 编 译 器 产 生 的 类 似 。

  3. 用 于 第 二 个 类 型 库 头 部 的 # include 语 句 。

  4. 结 尾 固 定 正 文 : 目 前 包 括 # pragma pack(pop) 。

以 上 这 些 部 分 除 头 部 固 定 正 文 和 结 尾 固 定 正 文 部 分 之 外 , 都 被 包 括 在 原 来 的 IDL 文 件 中 以 library 语 句 指 定 其 名 称 的 名 称 空 间 中 。 你 可 以 通 过 用 名 称 空 间 显 式限 定 或 包 括 如 下 语 句 从 类 型 库 头 部 使 用 该 名 称 。

using namespace MyLib

在 源 代 码 的 #import 语 句 之 后 立 即

名 称 空 间 可 用 #import 指 令 的 no_namespace 属 性 来 阻 止 。 但 阻 止 的 名 称 空 间 可能 导 致 名 称 冲 突 。 名 称 空 间 也 可 用 rename_namespace 属 性 重 新 换 名 。

编 译 器 提 供 完 全 路 径 给 需 要 依 赖 当 前 正 在 处 理 的 类 型 库 的 任 何 类 型 库 。 路 径 以注 释 格 式 写 入 到 由 编 译 器 为 每 个 处 理 的 类 型 库 生 成 的 类 型 库 头 部 (.TLH) 。

如 果 一 个 类 型 库 包 含 了 对 其 它 类 型 库 定 义 的 类 型 引 用 ,.TLH 文 件 将 包 括 以 下 注释 :

//

//Cross-referenced type libraries:

//

//# import "c:\path\typelib0.tlb"

//

在 #import 注 释 中 的 实 际 文 件 名 是 存 储 在 寄 存 器 中 交 叉 引 用 的 类 型 库 全 路 径 。如 果 你 遇 到 由 于 省 略 类 型 定 义 的 错 误 时 , 检 查 .TLH 头 部 的 注 释 , 看 哪 一 种 依 赖 类型 库 需 要 先 输 入 。 在 编 译 该 .TLI 文 件 时 可 能 的 错 误 有 语 法 错 误 ( 例 如C2143,C2146,C2321) 、 C2501( 缺 少 说 明 指 示 符 ) 或 C2433( 在 数 据 说 明 中 禁 止 ′

inline ′ ) 。

你 必 须 确 定 哪 些 依 赖 注 释 是 不 被 系 统 头 部 给 出 的 , 而 是 在 依 赖 类 型 库 的 #import 指 令 前 的 某 处 给 出 一 个 #import 指 令 以 消 除 这 些 错 误 。

exclude 属 性

exclude( “ 称 1 ” [, “ 名 称 2 ” ,...]) 名 称 1

被 排 斥 的 第 一 个 项名 称 2

被 排 斥 的 第 二 个 项 ( 如 有 必 要 )

类 型 库 可 能 包 含 在 系 统 头 部 或 其 它 类 型 库 内 定 义 的 项 的 定 义 。 该 属 性 可 用 于 从生 成 的 类 型 库 头 文 件 中 排 斥 这 些 项 。 这 个 属 性 可 带 任 意 数 目 的 参 量 , 每 个 参 量 是一 个 被 排 斥 的 高 级 类 型 库 项 目 :

high_method_prefix 属性

high_method_prefix(" Prefix ")

Prefix

被 使 用 的 前 缀

在 缺 省 的 情 况 下 , 高 级 错 误 处 理 属 性 和 方 法 用 一 个 无 前 缀 命 名 的 成 员 函 数 来 展示 。 这 个 名 称 来 自 于 类 型 库 。 high_method_prefix 属 性 说 明 一 个 前 缀 以 用 于 命名 这 些 高 级 属 性 和 方 法 。

high_property_prefixes 属 性

high_property_prefixes(" GetPrefix , "" PutPrefix , "" PutRefPrefix ")

GetPrefix

用 于 propget 方 法 的 前 缀

PutPrefix

用 于 propput 方 法 的 前 缀

PutRefPrefix

用 于 prop p utref 方 法 的 前 缀

在 缺 省 情 况 下 , 高 级 错 误 处 理 方 法 , 如 propget 、 propput 和 propputref, 分 别 采用 以 前 缀 Get 、Put 和 PutRef 命 名 的 成 员 函 数 来 说 明 。high_property_prefixes 属 性 用 于 分 别 说 明 这 三 种 属 性 方 法 的 前 缀 。

implementation_only 属 性

implementation_only 属 性 禁 止 .TLH 头 文 件 ( 基 本 头 文 件 ) 的 生 成 。 ±这 个 文 件 包括 了 所 有 用 于 展 示 类 型 库 内 容 的 说 明 。 该 .TLI 头 文 件 和 wrapper 成 员 函 数 的 实现 , 将 被 生 成 且 包 含 在 编 译 过 程 中 。

当 指 定 该 属 性 时 , 该 .TLI 头 部 的 内 容 将 和 用 于 存 放 普 通 .TLH 头 部 的 内 容 放 在 相同 的 名 称 空 间 。 此 外 , 该 成 员 函 数 不 会 作 为 联 编 说 明 。 implementation_only 属性 一 般 希 望 与 no_implementation 属 性 配 对 使 用 , 以 跟 踪 预 编 译 头 文 件 (PCH) 之外 的 实 现 。 一 个 有 no_implementation 属 性 的 #import 语 句 被 置 于 用 来 创 建 pch 的 源 区 域 中 , 结 果 PCH 将 被 一 些 源 文 件 所 用 。 一 个 带 implementation_only 属 性

的 #import 语 句 随 后 被 用 在 PCH 区 域 之 外 。 在 一 个 源 文 件 里 只 需 用 一 次 这 种 语句 。 这 将 生 成 不 需 对 每 个 源 文 件 进 行 额 外 重 编 译 的 所 有 必 要 的 wrapper 成 员 函数 。

注 意 : 一 个 #import 语 句 中 的 implementation_±only 属 性 必 须 和 相 同 类 型 库 中no_implementation 属 性 的 另 一 个 #import 语 句 配 套 使 用 。 否 则 , 将 产 生 编 译 错误 。 这 是 因 为 带 no_implementation 属 性 的 #import 语 句 生 成 的 wrapper 类 定义 需 要 编 译 implementation_only 属 性 生 成 的 语 句 实 现 。

include(...) 属 性

include( 名 称 1[, 名 称 2,...]) 名 称 1

第 一 个 被 强 制 包 含 的 项名 称 2

第 二 个 被 强 制 包 含 的 项 ( 如 果 必 要 )

类 型 库 可 能 包 含 在 系 统 头 部 或 其 它 类 型 库 中 定 义 的 项 的 定 义 。 #import 指 令 试图 用 自 动 排 斥 这 些 项 来 避 免 多 重 定 义 错 误 。 若 这 些 项 已 经 被 排 斥 , 象 警 告 C4192 所 指 出 的 那 样 , 且 它 们 不 应 该 被 排 斥 , 则 这 个 属 性 可 用 于 禁 止 自 动 排 斥 。 该 属 性可 带 任 意 数 目 的 参 量 , 每 个 参 量 应 是 被 包 括 的 类 型 库 项 的 名 称 。

inject_statement 属 性

inject_statement(" source_text ")

source_text

被 插 入 到 类 型 库 头 文 件 的 源 文 本 。

inject_statement 属 性 将 其 参 量 作 为 源 文 本 插 入 类 型 库 头 部 。 此 文 本 被 置 于 包括 头 文 件 中 类 型 库 内 容 的 名 称 空 间 说 明 的 起 始 处 。

named_guids 属 性

named_guids 属 性 让 编 译 器 定 义 和 初 始 化 模 板 LIBID_MyLib 、 CLSID_MyCoClass 、IID_MyInterface 和 DIID_MyDispInterface 的 旧 式 格 式 的 GUID 变 量 。

no_implementation 属性

该 属 性 阻 止 .TLI 头 文 件 的 生 成 , 这 个 文 件 包 含 wrapper 成 员 函 数 的 实 现 。 如 果指 定 这 个 属 性 , 则 展 示 类 型 库 项 说 明 的 .TLH 头 将 生 成 没 有 一 个 #include 语 句 包括 该 .TLI 头 文 件 。

该 属 性 与 implementation_only 属 性 配 套 使 用 。

no_auto_exclude 属 性

类 型 库 可 能 包 括 在 系 统 头 部 或 其 它 类 型 库 中 定 义 的 项 的 定 义 。 #import 试 图 通过 自 动 排 斥 这 些 项 来 避 免 多 重 定 义 错 误 。 当 这 样 做 时 , 每 个 被 排 斥 的 项 都 将 生 成一 个 C4192 警 告 信 息 。 你 可 禁 止 这 个 属 性 使 用 自 动 排 斥 。

no_namespace 属 性

#import 头 文 件 中 的 类 型 库 内 容 一 般 定 义 在 一 个 名 称 空 间 里 。 名 称 空 间 的 名 称在 原 来 IDL 文 件 的 library 语 句 中 指 定 。 如 果 指 定 no_namespace 属 性 , 编 译 器就 不 会 生 成 这 个 名 称 空 间 。

如 果 你 想 使 用 一 个 不 同 的 名 称 空 间 , 应 代 替 使 用 rename_namespace 属 性 。

raw_dispinterfaces 属性

raw_dispinterfaces 属 性 让 编 译 器 生 成 一 个 低 级 wrapper 函 数 。 该 函 数 用 于 调用 IDispatch::Invoke 和 返 回 HRESULT 错 误 代 码 的 dis p interface 方 法 和 属 性 。如 果 未 指 定 此 属 性 , 则 只 生 成 高 级 wrapper, 它 在 失 败 时 丢 弃 该 C++ 异 常 。

raw_interfaces_only 属 性

raw_interfaces_only 属 性 禁 止 生 成 错 误 处 理 wrapper 函 数 以 及 使 用 这 些wrapper 函 数 的 _ _ declspec( 属 性 ) 说 明 。

raw_interfaces_only 属 性 也 导 致 删 除 在 命 名 non __ property 函 数 中 的 缺 省 前缀 。 通 常 该 前 缀 是 raw _ 。 若 指 定 此 属 性 , 函 数 名 称 将 直 接 从 类 型 库 中 生 成 。

该 属 性 只 允 许 展 示 类 型 库 的 低 级 内 容 。raw_method_prefix 属性raw_method_prefix(" Prefix ")

Prefix

被 使 用 的 前 缀

用 raw_ 作 为 缺 省 前 缀 的 成 员 函 数 展 示 低 层 属 性 和 方 法 , 以 避 免 与 高 级 错 误 处 理成 员 函 数 的 名 称 冲 突 。 raw_method_prefix 属 性 用 于 指 定 一 个 不 同 的 前 缀 。

注 意 : raw_method_prefix 属 性 的 效 果 不 会 因 raw_method_prefix 属 性 的 存 在而 改 变 。 在 说 明 一 个 前 缀 时 ,raw_method_prefix 总 是 优 先 于raw_interfaces_only 。 若 两 种 属 性 用 在 同 一 个 #import 语 句 中 时 , 则 采 用raw_method_prefix 指 定 的 前 缀 。

raw_native_types 属 性

在 缺 省 情 况 下 , 高 级 错 误 处 理 方 法 在 BSTR 和 VARIANT 数 据 类 型 和 原 始 COM 界 面指 针 的 地 方 使 用 COM 支 持 类 _bctr_t 和 _variant_t 。 这 些 类 封 装 了 分 配 和 取 消分 配 这 些 数 据 类 型 的 存 储 器 存 储 的 细 节 , 并 且 极 大 地 简 化 了 类 型 造 型 和 转 换 操作 。 raw_native_types 属 性 在 高 级 wrapper 函 数 中 禁 止 使 用 这 些 COM 支 持 类 , 并 强 制 替 换 使 用 低 级 数 据 类 型 。

raw_property_prefix 属 性

raw_property_prefix(" GetPrefix "," PutPrefix "," PutRefPrefix ")

GetPrefix

用 于 propget 方 法 的 前 缀

PutPrefix

用 于 propput 方 法 的 前 缀

PutRefPrefix

用 于 propputref 方 法 的 前 缀

在 缺 省 情 况 下 , 低 级 方 法 propget 、 propput 和 propputref 分 别 用 后 缀 为 get_ 、put_ 和 putref_ 的 成 员 函 数 来 展 示 。 这 些 前 缀 与 MIDL 生 成 的 头 文 件 中 的 名 称 是兼 容 的 。 raw_property_prefixes 属 性 分 别 用 于 说 明 这 三 个 属 性 方 法 的 前 缀 。

rename 属 性

rename(" O ldNam e , "" NewNam e ")

O ldName

类 型 库 中 的 旧 名

NewName

用 于 替 换 旧 名 的 名 称

rename 属 性 用 于 解 决 名 称 冲 突 的 问 题 。 若 该 属 性 被 指 定 , 编 译 器 将 在 类 型 库 中的 OldName 的 所 有 出 现 处 用 结 果 头 文 件 中 用 户 提 供 的 NewName 替 换 。

此 属 性 用 于 类 型 库 中 的 一 个 名 称 和 系 统 头 文 件 中 的 宏 定 义 重 合 时 。 若 这 种 情 况未 被 解 决 , 则 将 产 生 大 量 语 法 错 误 , 如 C2059 和 C2061 。

注 意 : 这 种 替 换 用 于 类 型 库 的 名 称 , 而 不 是 用 于 结 果 头 文 件 中 的 名 称 。

这 里 有 一 个 例 子 : 假 设 类 型 库 中 有 一 个 名 称 为 MyParent 的 属 性 , 且 头 文 件 中 定 义了 一 个 用 在 #import 之 前 的 宏 GetMyParent 。 由 于 GetMyParent 是 用 于 错 误 处 理属 性 get 的 一 个 wrapper 函 数 的 缺 省 名 称 , 所 以 将 产 生 一 个 名 称 冲 突 。 为 解 决 这个 问 题 , 使 用 #import 语 句 中 的 以 下 属 性 :

rename("MyParent","MyParentX")

该 语 句 将 重 新 命 名 类 型 库 中 的 名 称 MyParent, 而 试 图 重 新 命 名 GetMyParent wrapper 名 称 将 会 出 错 :

rename("GetMyParent","GetMyParentX")

这 是 因 为 名 称 GetMyParent 只 出 现 在 结 果 类 型 库 头 文 件 中 。

rename_namespace 属 性

rename_namespace(" NewNam e ")

NewName

名 称 空 间 的 新 名 称

rename_namespace 属 性 用 于 重 新 命 名 包 含 类 型 库 内 容 的 名 称 空 间 。 它 带 有 一 个指 定 名 称 空 间 新 名 newname 的 参 量 。

消 除 名 称 空 间 可 以 使 用 no_namespace 属 性 。

C++ 特 殊 处 结 束#include 指令

#include 指 令 告 诉 预 处 理 器 处 理 一 个 指 定 文 件 的 内 容 , 就 象 这 些 内 容 以 前 就 在这 条 指 令 出 现 的 源 程 序 中 。 你 可 以 把 常 量 和 宏 定 义 放 在 包 含 文 件 中 , 然 后 用#include 指 令 把 这 些 定 义 加 到 任 何 源 文 件 中 。 包 含 文 件 对 于 外 部 变 量 和 复 杂 数据 类 型 结 合 的 说 明 也 是 有 用 的 。

你 只 需 在 为 此 目 的 创 建 的 一 个 包 含 文 件 中 定 义 和 命 名 这 些 类 型 一 次 。

语 法

# include " path-spec " # include <path-spec>

path_spec 是 一 个 前 面 有 目 录 说 明 的 任 选 文 件 名 。 这 个 文 件 名 必 须 命 名 一 个 现 存文 件 。

path_spec 的 语 法 依 赖 于 编 译 该 程 序 的 操 作 系 统 。

这 两 种 语 法 格 式 都 导 致 用 已 说 明 的 包 含 文 件 的 全 部 内 容 来 替 换 该 指 令 。 两 种 格式 的 区 别 在 于 路 径 未 完 整 指 定 时 预 处 理 器 搜 索 头 文 件 的 顺 序 。

语法格式 动作

引号格式 这种格式指示预处理器先在包含 #include 语句的文件的相同 目 录 内 搜 索 , 然 后 在 任 何 包 括 该 文 件 的 目 录 中 搜 索 。 随后 预 处 理 器 沿 着 /I 编 译 器 选 项 指 定 的 路 径 搜 索 , 最后是在INCLUDE 环境变量说明的路径搜索

尖括号格式 这种格式指示预处理器首先在 /I 编译器选项指定的路径中搜索包含文件。然后在 INCLUDE 环境变量说明的路径中搜索

一 旦 预 处 理 器 找 到 指 定 文 件 , 它 就 立 即 停 止 搜 索 。 如 果 用 双 引 号 给 出 一 个 明 确 完

整 的 包 含 文 件 的 路 径 , 预 处 理 器 将 只 搜 索 该 路 径 规 格 而 忽 略 标 准 目 录 。

如 果 在 双 引 号 间 的 文 件 名 不 是 一 个 完 整 的 路 径 规 格 , 预 处 理 器 将 先 搜 索 “ 父 ” 文件 的 目 录 。父 文 件 是 一 个 包 含 #include 指 令 的 文 件 。例 如 , 如 果 你 把 名 称 为 file2 的 文 件 包 括 在 一 个 名 称 为 file1 的 文 件 中 ,file1 就 是 父 文 件 。

包 含 文 件 可 被 嵌 套 ; 这 指 的 是 一 个 #include 指 令 出 现 在 以 另 一 个 #include 指 令

命 名 的 文 件 里 。 例 如 , 以 上 的 文 件 file2, 可 包 含 文 件 file3, 在 这 种 情 况下 ,±file 1是 file2 的 父 文 件 , 而 且 是 file3 的 祖 父 文 件 。

当 包 含 文 件 嵌 套 时 , 目 录 搜 索 首 先 由 父 文 件 的 目 录 开 始 , 然后 , 搜 索 祖 父 文 件 的 目录 。

因 此 , 搜 索 从 包 含 当 前 处 理 源 文 件 的 目 录 开 始 , 若 文 件 未 找 到 , 搜 索 就 转 到 /I 编译 器 选 项 指 定 的 目 录 , 最 后 搜 索 include 环 境 变 量 指 定 的 目 录 。

下 面 的 例 子 给 出 使 用 尖 括 号 的 文 件 包 括 :

# include <stdio.h>

这 个 例 子 把 名 称 为 STDIO.H 的 文 件 内 容 加 入 到 源 程 序 中 。 尖 括 号 指 示 预 处 理 器在 搜 索 完 /I 编 译 器 选 项 说 明 的 目 录 之 后 , 搜 索 STDIO.H 的 环 境 变 量 指 定 的 目 录 。下 面 的 例 子 给 出 用 引 号 格 式 的 文 件 包 括 :

# include "defs.h"

这 个 例 子 把 DEFS.H 指 定 的 文 件 内 容 加 入 源 程 序 。 双 引 号 标 记 意 味 着 预 处 理 器 首先 搜 索 包 含 父 源 文 件 的 目 录 。

包 含 文 件 的 嵌 套 可 高 达 10 层 , 只 要 在 处 理 嵌 套 的 #include 指 令 时 , 预 处 理 器 就会 不 断 地 把 包 含 文 件 加 入 到 最 初 的 源 文 件 中 。

Microsoft 特 殊 处 →

为 了 定 位 可 包 括 源 文 件 , 预 处 理 器 首 先 搜 索 /I 编 译 器 选 项 指 定 的 目 录 。 若 /I 选项 未 给 定 或 已 失 败 , 预 处 理 器 就 用 INCLUDE 环 境 变 量 搜 索 尖 括 号 内 的 包 含 文 件 。INCLUDE 环 境 变 量 和 /I 编 译 器 选 项 可 包 含 用 分 号 分 开 的 多 个 路 径 。 若 在 /I 选 项的 部 分 或 在 INCLUDE 环 境 变 量 里 有 多 于 一 个 的 目 录 , 预 处 理 器 将 以 它 们 出 现 的 顺序 对 它 们 进 行 搜 索 。

例 如 , 命 令 :

CL /ID :\MSVC\INCLUDE MYPROG.C

导 致 预 处 理 器 在 目 录 D:\MSVC\INCLUDE 中 搜 索 诸 如 STDIO.H 的 包 含 文 件 。 命 令 : SET INCLUDE=D:\MSVC\INCLUDE

CL MYPROG.C

有 相 同 的 作 用 。 如 果 所 有 搜 索 都 失 败 了 , 将 产 生 一 个 致 命 编 译 错 误 。

如 果 用 包 括 一 个 冒 号 的 路 径 ( 例 如 ,F:\MSVC\SPECIAL\INCL\TEST.H) 来 完 整 地 说明 一 个 包 含 文 件 的 文 件 名 , 预 处 理 器 将 沿 此 路 径 搜 索 。

对 于 指 定 为 #include "path_spec" 的 包 含 文 件 , 目 录 搜 索 将 从 父 文 件 的 目 录 开 始 , 然 后 搜 索 祖 父 文 件 的 目 录 。 因 此 , 搜 索 将 从 包 含 当 前 处 理 的 #include 指 令 的 源文 件 的 目 录 开 始 , 如 果 没 有 祖 父 文 件 或 文 件 未 找 到 , 搜 索 将 继 续 , 就 像 文 件 名 包括 在 尖 括 号 中 一 样 。

Microsoft 特 殊 处 结 束#line 指 令

#line 指 令 告 诉 预 处 理 器 将 编 译 器 内 部 存 储 的 行 号 和 文 件 名 转 变 为 一 个 给 定 的行 号 和 文 件 名 。 编 译 器 使 用 该 行 号 和 文 件 名 指 出 编 译 过 程 中 发 现 的 错 误 。 行 号一 般 指 的 是 当 前 输 入 行 , 文 件 名 指 当 前 输 入 文 件 。 每 处 理 一 行 , 行 号 就 增 1 。

语 法

# line

数 字 序 列 “ 文 件 名 ” opt

数 字 序 列 的 值 可 以 是 任 何 整 型 常 数 。 宏 替 换 可 在 预 处 理 语 言 符 号 中 执 行 , 但 结 果

必 须 求 值 为 正 确 的 语 法 。 文 件 名 可 以 是 任 意 字 符 的 组 合 , 且 应 括 在 双 引 号 ( “ ” ) 间 。 如 果 省 略 文 件 名 , 则 前 面 的 文 件 名 保 持 不 变 。

你 可 以 通 过 编 写 一 个 #line 指 令 来 改 动 源 行 号 和 文 件 名 。 翻 译 器 使 用 行 号 和 文件 名 来 确 定 预 定 义 宏 __ FILE _ __ _LINE _ _的 值 。 你 可 以 使 用 这 些 宏 把 自 描 述 错 误 消 息 加 入 到 程 序 文 本 中 。 有 关 这 些 宏 的 更 多 信 息 参 见 预 定 义 的 宏 。

__FILE _ _ 宏 扩 展 成 内 容 为 用 双 引 号 ( “” ) 括 起 的 文 件 名 的 一 个 字 符 串 。 ±

如 果 你 改 变 行 号 和 文 件 名 , 编 译 器 将 忽 略 原 有 的 值 , 用 新 值 继 续 处 理 。 #line 指令 通 常 被 程 序 生 成 器 用 来 生 成 指 向 最 初 源 程 序 的 错 误 消 息 , 而 不 是 生 成 程 序 。

下 面 的 例 子 用 于 说 明 #line 以 及 _ _ LINE _ __ _FILE _ _ 宏 。 在 这 个 语 句 中 , 内 部 存储 的 行 号 设 置 为 151, 文 件 名 改 为 copy.c 。

# line 151 "copy.c"

在 这 个 例 子 中 , 若 一 个 给 定 的 “ 断 言 ” (assertion) 不 为 真 , ±则宏 ASSERT 使 用 预定 义 宏 __ LINE _ __ _FILE _ _ 打 印 出 一 个 关 于 源 文 件 的 错 误 消 息 。

# define ASSERT(cond)

if( !(cond) ) \

{ printf("assertion error line %d, file(%s)\n",\

__ LINE _ _, _ _ FILE _ _ ); }

Null 指 令

空 预 处 理 器 指 令 是 一 行 中 一 个 单 独 的 数 字 标 号 (#), 无 任 何 作 用 。

语 法

#

#undef 指 令

正 如 其 名 所 隐 含 的 ,#undef 指 令 取 消 ( 反 定 义 ) 一 个 原 来 由 #define 指 令 创 建 的 名称 。

语 法

# undef

标 识 符

#undef 指 令 取 消 标 识 符 的 当 前 定 义 。 其 结 果 是 , 标 识 符 的 每 次 出 现 都 将 被 预 处理 器 所 忽 略 。 为 取 消 一 个 用 #undef 的 宏 定 义 , 只 须 给 出 宏 的 标 识 符 , 不 须 给 出 参数 表 。

你 也 可 以 将 #undef 指 令 用 于 一 个 原 来 未 定 义 的 标 识 符 。 这 将 确 认 这 个 标 识 符 是未 定 义 的 。 宏 替 换 不 能 在 #undef 语 句 中 执 行 。

#undef 指 令 通 常 和 一 个 #define 指 令 匹 配 , 以 在 源 程 序 中 创 建 一 个 区 域 , ±在 这 个区 域 中 一 个 标 识 符 有 其 特 定 的 含 义 。 例 如 , 源 程 序 的 一 个 特 有 函 数 可 以 使 用 显 式常 量 定 义 不 影 响 程 序 余 下 部 分 的 环 境 特 定 值 。 #undef 指 令 也 可 与 #if 指 令 配 对以 控 制 源 程 序 的 条 件 编 译 过 程 。有 关 更 多 信 息 参 见“ #if 、#elif 、#else 和 #endif 指 令 ”。

下 面 的 例 子 中 ,#undef 指 令 取 消 了 一 个 符 号 常 量 和 一 个 宏 的 定 义 , 注 意 该 指 令 只给 出 了 宏 的 标 识 符 。

# define WIDTH 80

# define ADD(X,Y) (X)+(Y)

.

.

.

# undef WIDTH # undef ADD

Microsoft 特 殊 处 →

宏 可 通 过 采 用 /U 选 项 的 命 令 行 反 定 义 , 此 命 令 行 后 跟 反 定 义 的 宏 名 称 。 此 命 令与 在 文 件 开 头 处 的 #undef 宏 名 称 语 句 序 列 的 作 用 是 相 等 的 。

Microsoft 特 殊 处 结 束

预 处 理 器 操 作 符

#define 指 令 的 文 本 中 有 四 种 预 处 理 器 特 有 的 操 作 符 ( 它 们 的 总 结 参 见 下 面 的表 ) 。

字 符 化 、 字 符 串 化 和 语 言 符 号 粘 贴 操 作 符 将 在 下 面 三 章 中 讨 论 。 defined 操 作符 的 信 息 参 见 “ #if 、 #elif 、 #else 和 #endif 指 令 ”。

运算符 动作

字符串化操作符 (#) 将相应实参置于双引号内

字符化操作符 (#@) 将 相 应 的 参 量 置 于 单 引 号 内 , 且 将 其 作 为字符处理 (Microsoft 特殊处 )

语言符号粘贴操作符 (##) 可 将 语 言 符 号 作 为 实 参 使 用 , 且 将 其 合 并

为其它 的语言符号

续 表

定义的操作符 简化在某特定宏指令中复合表达式的写法

字 符 串 化 操 作 符 (#)

数 字 符 号 或 “ 字 符 串 化 ” 操 作 符 (#) 将 宏 参 数 ( 扩 展 后 ) 转 化 为 字 符 串 常 量 。 它 只用 于 带 参 量 的 宏 。 如 果 它 在 宏 定 义 中 的 一 个 形 式 参 量 之 前 , 宏 调 用 传 给 的 实 际 参量 就 被 括 在 双 括 号 中 , 且 被 看 作 为 一 个 字 符 串 文 字 。 然 后 该 字 符 串 文 字 将 替 换 该宏 定 义 中 操 作 符 和 形 参 组 合 的 每 次 出 现 。

实 参 的 第 一 个 语 言 符 号 之 前 和 最 后 一 个 语 言 符 号 之 后 的 空 白 被 忽 略 。 实 参 中 语言 符 号 之 间 的 所 有 空 白 在 结 果 字 符 串 语 义 中 都 被 看 作 为 一 个 空 格 。 因 此 , 若 实 参中 的 一 个 注 解 出 现 在 两 个 语 言 符 号 之 间 , 它 将 被 看 作 为 一 个 空 格 。 结 果 字 符 串 文字 自 动 地 与 任 何 仅 用 空 格 分 开 的 相 邻 字 符 串 文 字 连 接 。

此 外 , 如 果 一 个 包 含 在 参 量 里 的 字 符 在 用 作 一 个 字 符 串 文 字 ( 例 如 , 双 引 号 (") 或反 斜 杠 (\) 字 符 ) 时 通 常 需 要 一 个 转 义 序 列 , ±必 要 的 转 义 反 斜 杠 被 自 动 地 插 入 字符 之 前 。 下 面 的 例 子 给 出 了 一 个 包 含 字 符 串 化 操 作 符 的 宏 定 义 和 一 个 调 用 该 宏的 main 函 数 :

# define stringer(x) printf(#x "\n")

void main( )

{

stringer(In quotes in the printf function call\n);

stringer("In quotes when printed to the screen"\n);

stringer("This:\" prints an escaped double quote");

}

这 种 调 用 在 预 处 理 时 会 被 扩 展 , 产 生 如 下 代 码 :

void main()

{

printf("In quotes in the printf function call\n" "\n");

printf("\"In quotes when printed to the screen\"\n" "\n");

printf("\"This; \\\" prints an escaped double quote \"" "\n");

}

当 运 行 该 程 序 时 , 每 行 的 屏 幕 输 出 如 下 :

In quotes in the printf function call "In quotes when printed to the screen"

"This; \" prints an escaped double quot ation mark "

Microsoft 特 殊 处 →

Microsoft C( 版 本 6.0 及 更 早 版 本 ) 扩 展 ANSI C 的 标 准 ,ANSI C 扩 展 在 字 符 串文 字 和 字 符 常 量 中 出 现 的 宏 形 式 参 量 不 再 被 支 持 。 依 赖 于 此 扩 展 的 代 码 应 该 使用 字 符 串 化 操 作 符 (#) 重 写 。

Microsoft 特 殊 处 结 束

字 符 化 操 作 符 (#@)

Microsoft 特 殊 处 →

字 符 化 操 作 符 只 可 用 于 宏 参 量 , 若 宏 定 义 中 #@ 在 一 个 形 参 前 , 则 实 参 应 被 放 在 单引 号 中 , 在 宏 扩 展 时 作 为 一 个 字 符 处 理 。 例 如 :

# define makechar(x) #@x 将 语 句 :

a=makechar(b); 扩 展 为 :

a='b';

单 引 号 字 符 不 能 用 于 字 符 化 操 作 符 。

Microsoft 特 殊 处 结 束

语 言 符 号 粘 贴 操 作 符 (##)

双 数 字 语 言 符 号 或 “ 语 言 符 号 粘 贴 ” 操 作 符 (##), 有 时 称 作 “ 合 并 ” 操 作 符 , 用于 类 对 象 宏 和 类 函 数 宏 中 。 它 允 许 将 分 开 的 语 言 符 号 加 入 一 个 单 个 语 言 符 号 中 , 因 此 不 能 是 宏 定 义 的 第 一 个 语 言 符 号 或 最 后 一 个 语 言 符 号 。

如 果 一 个 宏 定 义 中 的 形 参 在 语 言 符 号 粘 贴 操 作 符 的 前 后 , 则 形 参 将 立 即 被 未 扩 展的 实 参 替 换 。 在 替 换 之 前 不 对 参 量 执 行 宏 扩 展 。

然 后 , 语 言 符 号 字 符 串 中 语 言 符 号 粘 贴 操 作 符 的 每 次 出 现 将 被 删 除 , 其 前 后 的 语言 符 号 将 被 合 并 。 其 结 果 语 言 符 号 必 须 是 一 个 有 效 的 语 言 符 号 。 若 其 有 效 , 如 果该 语 言 符 号 代 表 一 个 宏 名 称 , 则 扫 描 它 以 发 现 可 能 的 替 换 。 该 标 识 符 表 示 在 替 换

前 程 序 中 己 知 合 并 的 语 言 符 号 的 名 称 。 每 个 语 言 符 号 都 代 表 一 个 在 程 序 中 或 在编 译 器 命 令 行 中 定 义 的 语 言 符 号 。

该 操 作 符 前 后 的 空 白 是 任 意 的 。

如 下 例 子 说 明 了 程 序 输 出 中 字 符 串 化 操 作 符 和 语 言 符 号 粘 贴 操 作 符 的 用 法 : # define paster(n) printf("token" #n "=%d",take n ##n)

int token9=9;

若 一 个 宏 用 一 个 类 似 于 下 面 的 数 值 参 量 调 用 :

paster(9); 宏 将 生 成 :

printf("token" "9" "=%d",token9); 它 变 成 为 :

printf("token9 = %d", token9 );

对 宏 扩 展 的 预 处 理 在 所 有 那 些 不 是 预 处 理 指 令 的 行 ( 第 一 个 非 空 白 字 符 不 是 # 的行 ), 以 及 其 指 令 并 未 作 为 条 件 编 译 的 一 部 分 而 忽 略 的 行 中 进 行 。“ 条 件 编 译 ” 指令 允 许 通 过 检 测 一 个 常 量 表 达 式 或 标 识 符 以 决 定 在 预 处 理 过 程 中 哪 个 文 本 块 送入 编 译 器 、 哪 个 文 本 块 从 源 文 件 中 删 除 , 并 以 此 种 方 式 控 制 一 个 源 文 件 中 某 部 分的 编 译 。

#define 指 令 通 常 使 用 有 意 义 的 标 识 符 与 常 量 、 关 键 字 、 常 用 语 句 和 表 达 式 关联 。 表 示 常 量 的 标 识 符 有 时 被 称 作 “ 符 号 常 量 ” 或 “ 显 式 ” 常 量 。 表 示 语 句 或

表 达 式 的 常 量 称 为 “ 宏 ”。 在 本 预 处 理 器 文 档 中 , 只 使 用 术 语 “ 宏 ”。

当 宏 的 名 称 在 程 序 源 文 本 或 在 某 些 其 它 预 处 理 器 命 令 的 参 量 中 被 识 别 时 , 它 被 处理 为 对 该 宏 的 调 用 。 宏 名 称 被 宏 体 的 一 个 拷 贝 所 替 换 。 若 该 宏 接 受 参 量 , 宏 名 称后 的 实 参 就 会 替 换 宏 体 中 的 形 参 。 用 宏 体 中 处 理 的 拷 贝 来 替 换 一 个 宏 调 用 的 过程 , 称 为 宏 调 用 的 “ 扩 展 ”。

实 际 的 术 语 中 有 两 种 类 型 的 宏 。“ 类 对 象 ” 宏 不 带 参 量 , 而 “ 类 函 数 ” 宏 可 定 义为 带 参 量 。因 此 它 们 的 形 式 和 功 能 都 象 函 数 调 用 , 由 于 宏 不 生 成 实 际 的 函 数 调 用 , 所 以 有 时 可 用 宏 替 代 函 数 调 用 使 程 序 运 行 得 更 快 ,( 在 C++ 中 ,inline 函 数 通 常 是一 个 好 方 法 ), 然 而 , 如 果 不 小 心 的 定 义 和 使 用 宏 , 也 可 能 造 成 麻 烦 。 在 带 参 量 的宏 定 义 时 , 你 必 须 使 用 括 号 以 保 持 一 个 表 达 式 中 正 常 的 优 先 级 , 同 时 宏 也 不 能 正确 地 处 理 具 有 副 作 用 的 表 达 式 。 有 关 更 多 的 信 息 参 见 “ #define 指 令 ” 中 的 例子 getrandom 。

  • 旦 你 定 义 了 一 个 宏 , 你 不 能 不 经 取 消 该 宏 原 有 定 义 , 而 重 新 定 义 它 为 一 个 不 同的 值 。 但 可 用 正 好 相 同 的 定 义 来 重 定 义 该 宏 , 因 此 , 一 个 程 序 中 宏 的 相 同 定 义 可出 现 多 次 。

#undef 指 令 用 于 取 消 宏 的 定 义 。 一 旦 取 消 该 宏 的 定 义 , 就 可 重 新 定 义 该 宏 为 一个 不 同 的 值 。 #define 和 #undef 两 节 分 别 详 细 讨 论 了 #define 和 #undef 指 令 。

宏 和 C++

C++ 提 供 了 一 些 新 的 功 能 。 其 中 有 些 功 能 替 代 了 原 来 由 ANSI C 所 提 供 的 功 能 。这 些 新 的 功 能 增 强 了 类 型 安 全 性 和 该 语 言 的 可 预 测 性 :

  • 在 C++ 中 , 以 const 说 明 的 对 象 可 用 于 常 量 表 达 式 中 , 这 使 程 序 可 以

说 明 有 类 型 和 值 信 息 的 常 量 , 以 及 能 被 调 试 器 逐 个 字 符 检 查 的 枚 举值 的 常 量 。 使 用 预 处 理 器 指 令 #define 定 义 常 量 并 不 精 确 。 除 非 在程 序 中 找 到 一 个 带 地 址 的 表 达 式 , 否 则 一 个 const 对 象 将 不 分 配 任何 存 储 。

  • C++ 联 编 函 数 替 代 了 函 数 类 型 宏 , 相 对 于 宏 来 说 使 用 联 编 函 数 的 优 势在 于 :

  • 类 型 安 全 性 。 联 编 函 数 和 一 般 函 数 一 样 需 进 行 相 同 的 类 型 检 测 , 宏无 类 型 安 全 性 检 测 。

  • 纠 正 具 有 副 作 用 的 参 量 处 理 。 联 编 函 数 在 进 入 函 数 体 之 前 对 参 量 的表 达 式 求 值 。 因 此 , 一 个 有 副 作 用 的 表 达 式 将 是 安 全 的 。

对 于 联 编 函 数 的 更 多 信 息 参 见 inline 、 _ _ inline 节 。

为 了 向 下 兼 容 ,Microsoft C++ 保 留 了 所 有 在 ANSI C 和 更 早 C++ 规 格 中 的 预 处 理器 功 能 。

预 定 义 宏

编 译 器 可 识 别 六 种 预 定 义 的 ANSI C 宏 ( 参 见 表 1.1), 而 Microsoft C++ 实 现 提 供更 多 的 预 定 义 宏 ( 参 见 表 1.2) 。 这 些 宏 不 带 参 量 , 但 不 能 被 重 定 义 。 它 们 的 值 ( 除

__LINE _ __ _FILE _ _ 外 ) 必 须 是 经 过 编 译 的 常 量 。 下 面 列 出 的 一 些 预 定 义 宏 须 用 多 个 值 来 定 义 , 它 们 的 值 可 在 Visual C++ 开 发 环 境 中 选 择 相 应 的 菜 单 选 项 来 设置 或 采 用 命 令 行 开 关 。 更 多 的 信 息 参 见 下 表 。

表 1.1 ANSI 预 定 义 宏

宏 说明

__ DATE _ _ 当 前 源 文 件 的 编 译 日 期 。 日 期 是 格 式 为 Mmm dd yyyy 的字符 串 文 字 。 月 份 名 称 Mmm 与 在 TIME.H 中 说 明 的 库 函 数asctime 产生的日期一样

__ FILE _ _ 当前源文件名称。 __ FILE _ _扩 展 为 用 双 引 号 括 起 的 一 个 字 符串

__ LINE _ _ 当 前 源 文 件 的 行 号 。 该 行 号 是 一 个 十 进 制 整 型 常 量 。 可 用

一个 #line 指令修改

__ STDC _ _ 指出与 ANSI C 标准的完全一致性。仅当给出 /Za 编译器选项 且 不 编 译 C++ 代码时定义为整型量 1; 否则是不确定的

__ TIME _ _ 当前文件的最近编译时间。该时间是格式为 hh:mm:ss 的字符串文字

__ TIMESTAMP _ _ 当 前 源 文 件 的 最 近 修 改 日 期 。 日 期 是 格 式 为 Ddd Mmm Date hh:mm:ss yyyy 的 字 符 串 文 字 , 这 里 Ddd 是 星 期 几 的 简写 ,Date 是从 1 到 31 的一个整数

表 1.2 Microsoft 特 殊 预 定 义 的 宏

宏 说明

__ CHAR_UNSIGNED 缺省 char 类型是无符号的 , 当 指 定 /J 时定义的

__ cplusplus 仅为 C++ 程序定义

续 表

__ CPPRTTI 定 义 为 用 /GR 编译的代码 ( 允许运行时类型信息 )

__ CPPUNWIND 定 义 为 用 /GX 编译的代码 ( 允许异常处理 )

__ DLL 指定 /MD 或 /MDd( 多线程 DLL) 时定义的

__ M_ALPHA 为 DEC ALPHA 平台定义 , 使用 ALPHA 编译器时定义为 1, 若使用另一个编译器时不定义

__ M _ IX86 为 x86 处理器定义 , 参见表 1.3

__ M _ MPPC 为 Power Macintosh 平台定义 , 缺省为 601(/QP601) 参见表 1.4

__ M _ MRX000 为 MIPS 平台定义 , ±缺省为 4000(/QMR4000), 参见表 1.5

__ M _ PPC 为 PowerPC 平台定义 , 缺省为 604(/QP604), 参见表 1.6

__ MFC _ VER 为 MFC 版本定义 , 为 Microsoft Founndation 类库 4.21 定义为 0x0421, 它总是定义的

__ MSC _ EXTENSIONS 该 宏 在 使 用 /Ze 编 译 选 项 ( 缺省值 ) 时 定 义 , 定 义 时 其 值 总为 1

__ MSC _ VER 定 义 编 译 器 版 本 , 对于 Microsoft Visual C++ 6.0 定义为 1200, 它总是定义的

__ MT 当指定 /MD 或 /MDd( 多线程 DLL) 或 /MT 或 /MTd( 多线程 ) 选项 时 定 义

__ WIN32 为 Win32 应用程序而定义。它总是定义的

如 下 表 所 示 , 编 译 器 对 反 映 处 理 器 选 项 的 预 处 理 器 标 识 符 产 生 一 个 值 。

表 1.3 _M_IX86 的 值

开发者的选项

命令行选项

返回值

Blend

Pentium

/GB

/G5

_M_IX86=500( 缺 省 值 。 将 来译 器 将 给 出 一 个 不 同 的 值 以主处理器 )

_M_IX86=500

的影

编响

Pentium Pro

/G6

_M_IX86=600

80386

/G3

_M_IX86=300

80486

/G4

_M_IX86=400

表 1.4

_M_MPPC 的 值

开发者的选项

命令行选项

返 回 值

PowerPC 601

/QP601

_M_MPPC=601( 缺省值 )

PowerPC 603

/QP603

_M_MPPC=603

PowerPC 604

/QP604

_M_MPPC=604

PowerPC 620

/QP620

_M_MPPC=620

表 1.5

_M_MRX000 的 值

开发者选项

命令行选项

返 回 值

R4000

/QMR4000

_M_MRX000=4000( 缺省值 )

R4100

/QMR4100

_M_MRX000=4100

R4200

/QMR4200

_M_MRX000=4200

续 表

R4400 R4600 R10000

/QMR4400

/QMR4600

/QMR10000

_M_MRX000=4400

_M_MRX000=4600

_M_MRX000=10000

表 1.6

_M_PPC 的 值

开发者选项

命令行选项

返 回 值

PowerPC 601

/QP601

_M_PPC=601

PowerPC 603

/QP603

_M_PPC=603

PowerPC 604

/QP604

_M_PPC=604( 缺省值 )

PowerPC 620

/QP620

_M_PPC=620