3 章 说 明 和 类 型

本 章 描 述 变 量 、 函 数 和 类 型 的 说 明 与 初 始 化 。 C 语 言 包 括 一 个 标 准 数 据类 型 的 标 准 集 。

你 还 可 以 增 加 自 己 的 数 据 类 型 , 称 为 “ 派 生 的 类 型 ” , 即 通 过 已 经 定 义 的类 型 说 明 新 的 类 型 。

讨 论 的 主 题 如 下 :

  • 说 明 概 述

  • 存 储 类

  • 指 示 符

  • 类 型 修 饰 符

  • 说 明 符 和 变 量 说 明

  • 解 释 复 杂 说 明

  • 初 始 化

  • 基 本 类 型 的 存 储

  • 不 完 整 的 类 型

  • 类 型 定 义 说 明

  • 扩 展 存 储 类 属 性

说 明 概 述

  • 个 “ 说 明 “ 指 出 一 组 标 识 符 的 解 释 和 属 性 。

导 致 为 标 识 符 的 对 象 或 函 数 保 留 存 储 的 说 明 称 之 为 “ 定 义 ”。 变 量 、 函数 和 类 型 的 C 说 明 具 有 这 样 的 语 法 :

语 法说 明 :

说 明 指 示 符 初 始 化 说 明 符 表 opt

说 明 指 示 符 :

存 储 类 指 示 符 属 性 序 列 opt 说 明 指 示 符 opt

/* 属 性 序 列 opt 是 M icrosoft 特 殊 处 */

类 型 指 示 符 说 明 指 示 符 opt

类 型 修 饰 符 说 明 指 示 符 opt

初 始 化 说 明 符 表 :

初 始 化 说 明 符

初 始 化 说 明 符 表 初 始 化 说 明 符初 始 化 说 明 符 :

说 明 符

说 明 符 = 初 始 化 器

注 意 : 说 明 的 语 法 在 后 面 不 再 重 复 。 后 面 使 用 的 语 句 通 常 以 说 明 符 非 终结 符 开 头 。

初 始 化 说 明 符 表 中 的 说 明 包 含 命 名 的 标 识 符 ; 初 始 化 是 初 始 化 器 的 简

称 。 初 始 化 说 明 符 表 是 用 逗 号 分 隔 的 说 明 符 序 列 , 每 个 都 有 附 加 类 型 信息 或 一 个 初 始 化 器 或 两 者 都 有 。 说 明 符 包 含 任 何 说 明 的 标 识 符 。 说 明 指示 符 非 终 结 符 由 类 型 序 列 和 指 出 连 接 、 存 储 期 的 存 储 类 指 示 符 以 及 说 明符 表 示 的 实 体 类 型 最 小 的 部 分 组 成 。 因 此 , 说 明 由 存 储 类 指 示 符 、 类 型指 示 符 、 类 型 修 饰 符 、 说 明 符 和 初 始 化 器 的 某 种 组 合 组 成 。

说 明 可 以 包 含 属 性 序 列 中 列 出 的 一 个 或 多 个 任 选 属 性 。 这 些 M icrosoft 特 定 属 性 实 现 函 数 的 变 型 , 这 在 本 书 中 详 细 讨 论 , 对 于 属 性 列 表 , 参 见 本 卷后 面 的 附 录 A “ C 语 言 语 法 总 结 ”。

在 一 个 变 量 说 明 的 一 般 格 式 中 , 类 型 指 示 符 给 出 该 变 量 的 数 据 类 型 。 类型 指 示 符 可 以 是 复 合 的 ,可 以 用 const 或 volatile 修 饰 。 说 明 符 给 出 了 变量 名 称 , 说 明 一 个 数 组 或 指 针 类 型 的 修 饰 。 例 如 :

int const *fp;

说 明 一 个 名 称 为 fp 的 变 量 为 不 能 修 改 的 (const)int 值 的 指 针 。 你 可 以 使用 多 个 以 逗 号 分 隔 的 说 明 符 在 一 个 说 明 中 定 义 一 个 以 上 的 变 量 。

一 个 说 明 必 须 至 少 有 一 个 说 明 符 , 或 者 它 的 类 型 指 示 符 必 须 说 明 一 个 结构 标 志 、 联 合 标 志 或 一 个 枚 举 器 的 成 员 。 一 个 说 明 符 是 一 个 这 样 的 标 识符 ,可 以 分 别 用 方 括 号 ([])、 星 号 (*) 或 圆 括 号 (()) 修 饰 来 说 明 一 个 数 组 、 指针 或 函 数 。 当 你 说 明 简 单 变 量 ( 例 如 字 符 、 整 数 和 浮 点 项 ) 或 一 些 简 单 变量 的 结 构 和 联 合 时 ,该 说 明 符 也 是 一 个 标 识 符 。 有 关 更 多 信 息 , 参 见 本 章后 面 的 “ 说 明 符 和 变 量 说 明 ”。

所 有 定 义 都 隐 含 地 说 明 , 但 不 是 所 有 说 明 都 是 定 义 。 例 如 , 以 extern 存 储类 指 示 符 开 头 的 说 明 是 “ 引 用 ” , 而 不 是 “ 定 义 ” 说 明 。 如 果 外 部 变 量

在 其 定 义 之 前 被 引 用 , 或 者 如 果 它 定 义 在 另 一 个 使 用 的 源 文 件 中 , 必 须 使用 一 个 extern 说 明 。“ 引 用 ” 说 明 不 分 配 存 储 ,在 说 明 中 变 量 也 不 能 初 始化 。

在 变 量 说 明 中 需 要 一 个 存 储 类 或 一 个 类 型 ( 或 两 者 都 需 要 ) 。 除 了

__ declspec 外 , 在 一 个 说 明 中 只 允 许 有 一 个 存 储 类 指 标 符 , 不 是 所 有 的 存 储类 指 示 符 都 允 许 在 每 个 上 下 文 中 。

__ declspec 存 储 类 允 许 与 其 它 存 储 类 指 示 符 一 起 使 用 , 允 许 使 用 多 次 。 一个 说 明 的 存 储 类 指 示 符 影 响 被 说 明 的 项 是 如 何 存 储 和 初 始 化 的 、 以 及 程序 的 哪 部 分 可 以 引 用 该 项 。

定 义 在 C 中 的 存 储 类 指 示 符 终 结 符 包 括 auto 、 extern 、 registe r、 static 和typedef。 另 外 ,Microsoft C 包 括 存 储 类 指 示 符 终 结 符 _ _declspec 。 所 有 除typedef 和 _ _declspec 外 的 存 储 类 指 示 符 终 结 符 都 在 “ 存 储 类 ” 中 讨 论 。有 关 typedef 的 信 息 参 见 本 章 后 面 的 “ typedef 说 明 ”。 有 关 _ _declspec 的信 息 参 见 “ 扩 充 的 存 储 类 属 性 ”。

在 一 个 源 程 序 中 说 明 的 位 置 以 及 该 变 量 是 否 存 在 其 它 说 明 对 于 确 定 变 量的 生 存 期 是 重 要 的 因 素 。 可 以 有 多 个 重 新 说 明 , 但 只 有 一 个 定 义 。 但 一个 定 义 可 以 出 现 在 多 个 转 换 单 元 中 。 对 于 内 部 连 接 的 对 象 , 这 个 规 则 分别 应 用 于 每 个 转 换 单 元 , 因 为 内 部 连 接 的 对 象 对 一 个 转 换 单 元 来 说 是 唯一 的 。 对 于 外 部 连 接 的 对 象 , 这 个 规 则 应 用 于 整 个 程 序 。 有 关 可 见 性 的更 多 信 息 ,参 见 第 2 章的 “ 生 存 期 、 范 围 、 可 见 性 和 连 接 ”。

类 型 指 示 符 提 供 了 一 些 标 识 符 数 据 类 型 的 信 息 , 缺 省 类 型 指 示 符 是 int。

有 关 更 多 信 息 , 参 见 本 章 后 面 的 “ 类 型 指 示 符 ”。 类 型 指 示 符 也 可 以 定 义

类 型 标 志 、 结 构 和 联 合 组 成 成 分 名 称 以 及 枚 举 常 量 。 有 关 更 多 信 息 , 参见 本 章 后 面 的 “ 枚 举 说 明 ”、“ 结 构 说 明 ” 和 “ 联 合 说 明 ”。

有 两 个 类 型 修 饰 符 终 结 符 :const 和 volatile 。 这 些 修 饰 符 指 出 另 外 的 类 型特 性 , 它 们 仅 与 访 问 通 过 l 值 确 定 类 型 的 对 象 有 关 。 有 关 const 和 volatile 的 更 多 信 息 , 参 见 本 章 后 面 的 “ 类 型 修 饰 符 ”。 有 关 l 值 的 定 义 ,参 见 第4 章 “ 表 达 式 和 赋 值 ” 中 的 “ L 值 和 R 值 表 达 式 ”。

存 储 类

一 个 变 量 的 “ 存 储 类 ” 确 定 该 项 是 “ 全 局 的 ” 生 存 期 还 是 “ 局 部 的 ” 生存 期 。 C 调 用 这 两 个 生 存 期 :“ static ” 和 “ automatic ”。 一 个 具 有 全 局 生存 期 的 项 在 整 个 程 序 执 行 中 都 存 在 并 有 一 个 值 。 所 有 函 数 都 有 全 局 生 存期 。

自 动 变 量 或 具 有 局 部 生 存 期 的 变 量 , 在 每 次 把 控 制 传 给 定 义 它 们 的 块 时都 分 配 新 的 存 储 。 当 执 行 返 回 时 ,该 变 量 不 再 具 有 有 意 义 的 值 。

C 提 供 如 下 存 储 类 指 示 符 :

语 法

存 储 类 指 示 符 :

auto register static extern

typedef

_ _declspec( 扩 充 的 说 明 修 饰 符 序 列 )/* M icrosoft 特 定 的 */

除 了 __declspec 外 , 你 在 一 个 说 明 的 说 明 指 示 符 中 只 能 使 用 一 个 存 储 类 指示 符 。 如 果 没 有 存 储 类 指 示 符 ,在 一 个 块 中 的 说 明 建 立 自 动 对 象 。

用 auto 或 register 指 示 符 说 明 的 项 具 有 局 部 生 存 期 。 用 static 或 extern

指 示 符 说 明 的 项 具 有 全 局 生 存 期 。

因 为 typedef 和 _ _declspec 语 义 上 不 同 于 其 它 4 个 存 储 类 指 示 符 终 结 符 , 把 它 们 分 开 进 行 讨 论 。 有 关 typedef 的 特 定 信 息 ,参 见 “ typedef 说 明 ”。有 关

__ declspec 的 特 定 信 息 ,参 见 “ 扩 充 存 储 类 属 性 ”。

变 量 和 函 数 说 明 在 源 文 件 中 的 位 置 也 影 响 存 储 类 和 可 见 性 。 所 有 函 数 定义 外 面 的 说 明 被 说 成 出 现 在“ 外 部 层 ”。 函 数 定 义 内 部 的 说 明 出 现 在“ 内部 层 ”。

每 个 存 储 类 指 示 符 的 精 确 含 义 依 赖 于 两 个 因 素 :

该 说 明 出 现 在 外 部 层 还 是 内 部 层 。该 项 是 说 明 成 变 量 还 是 函 数 。

下 面 两 节 “ 外 部 层 说 明 的 存 储 类 指 示 符 ” 和 “ 内 部 层 说 明 的 存 储 类 指 示符 ” 描 述 了 每 种 说 明 中 的 存 储 类 指 示 符 终 结 符 并 解 释 了 从 变 量 中 忽 略 存储 类 指 示 符 的 缺 省 行 为 。“ 函 数 说 明 的 存 储 类 指 示 符 ” 讨 论 了 在 函 数 中使 用 存 储 类 指 示 符 。

外 部 层 说 明 的 存 储 类 指 示 符

外 部 变 量 是 文 件 范 围 的 变 量 , 它 们 定 义 在 任 何 函 数 的 外 面 , 对 于 很 多 函 数是 可 用 的 。 函 数 只 能 在 外 部 层 定 义 , 因 此 , 不 能 嵌 套 。 缺 省 地 ,所 有 同 名 称的 外 部 变 量 和 函 数 的 引 用 指 向 同 一 对 象 ,这 意 味 着 它 们 具 有 “ 外 部 连 接 ” ( 你 可 以 使 用 static 关 键 词 覆 盖 它 , 有 关 static 的 详 细 情 况 参 见 本 章 后 面的 信 息 )。

在 外 部 层 的 变 量 说 明 是 变 量 定 义 (“ 定 义 说 明 ” ) 或 其 它 地 方 定 义 的 变 量的 引 用 (“ 引 用 说 明 ” )。

  • 个 初 始 化 变 量 的 外 部 变 量 说 明 ( 隐 含 或 显 式 地 ) 是 该 变 量 的 一 个 定 义 说明 。 在 外 部 层 的 定 义 可 以 有 几 种 格 式 :

    • 你 用 static 存 储 类 指 示 符 说 明 的 变 量 。 你 可 以 用 一 个 常 量 表 达 式显 式 地 初 始 化 该 static 变 量 , 正 如 “ 初 始 化 ” 中 描 述 的 。 如 果 你 省略 该 初 始 化 器 , 该 变 量 缺 省 初 始 化 为 0, 例 如 , 这 里 有 两 个 定 义 变 量 k 的 语 句 。

static int k=16 static int k;

  • 一 个 你 在 外 部 层 显 式 初 始 化 的 变 量 。 例 如 ,int j=3; 是 变 量 j 的 一

个 定 义 。

在 外 部 层 说 明 变 量 时 ( 也 就 是 在 所 有 函 数 的 外 面 ), 你 可 以 使 用 static 或extern 存 储 类 指 示 符 或 整 个 地 省 略 该 存 储 类 指 示 符 。 你 不 能 在 外 部 层 使用 auto 和 register 存 储 类 指 示 符 终 结 符 。

  • 旦 一 个 变 量 在 外 部 层 定 义 了 , 它 在 余 下 的 转 换 单 元 中 是 可 见 的 。 该 变量 在 同 一 个 源 文 件 中 其 说 明 的 前 面 是 不 可 见 的 。 在 该 程 序 的 其 它 源 文 件中 也 是 不 可 见 的 , 除 非 有 一 个 引 用 说 明 使 它 成 为 可 见 的 , 正 如 下 面 说 明的 。

static 的 相 关 规 则 包 括 :

  • 所 有 块 外 面 的 以 不 带 static 关 键 字 方 式 说 明 的 变 量 总 是 在 整 个 程序 中 保 留 它 们 的 值 。 为 了 限 制 它 们 对 特 定 转 换 单 元 的 访 问 , 你 必 须使 用 static 关 键 字 , 这 给 它 们 “ 内 部 连 接 ”。 为 了 使 它 们 对 整 个 程序 而 言 是 全 局 的 , 省 略 显 式 存 储 类 或 使 用 关 键 字 extern( 参 见 下 面 表中 的 规 则 ), 这 给 它 们 “ 外 部 连 接 ”。 内 部 和 外 部 连 接 在 第 2 章 “ 程序 结 构 ” 中 的 “ 连 接 ” 中 讨 论 。

  • 你 可 以 在 一 个 程 序 中 的 外 部 层 一 个 变 量 仅 定 义 一 次 , 可 以 在 不 同 转

换 单 元 中 用 相 同 的 名 称 和 static 存 储 类 指 示 符 定 义 另 外 的 变 量 。由 于 每 个 static 定 义 仅 在 它 自 己 的 转 换 单 元 中 可 见 , 因 此 不 会 出 现冲 突 。 这 提 供 了 这 样 的 标 识 符 名 称 的 有 用 方 式 , 该 标 识 符 在 一 个 转换 单 元 的 函 数 中 实 现 共 享 , 但 对 其 它 转 换 单 元 是 不 可 见 的 。

  • static 存 储 类 指 示 符 也 可 以 应 用 于 函 数 。 如 果 说 明 一 个 函 数 为static, 它 的 名 称 在 被 说 明 的 文 件 之 外 是 不 可 见 的 。

使 用 extern 的 规 则 是 :

  • extern 存 储 类 指 示 符 说 明 一 个 其 它 地 方 说 明 的 变 量 的 引 用 , 你 可 以使 用 一 个 extern 说 明 使 其 它 源 文 件 中 的 定 义 是 可 见 的 , 或 者 使 一 个变 量 在 相 同 源 文 件 中 其 定 义 的 前 面 是 可 见 的 。 一 旦 你 在 外 部 层 说 明

了 一 个 变 量 的 引 用 , 该 变 量 在 说 明 引 用 出 现 的 转 换 单 元 的 余 下 部 分都 是 可 见 的 。

  • 对 于 一 个 有 效 的 extern 引 用 , 所 指 的 变 量 必 须 定 义 一 次 , 而 且 在 外部 层 仅 一 次 。 这 个 定 义 ( 没有 extern 存 储 类 ) 可 以 在 任 何 构 成 程 序的 转 换 单 元 中 。

例子

如下例子说明了外部说明 :

/************************************************

SOURCE FILE ONE

*************************************************/ extern int i; /* 引用 i, 定义在下面 */

void next(void); /* 函数原型 */

void main()

{

i++;

printf("%d\n",i); /*i 等于 4*/ next();

}

int i=3; /*i 的定义 */

void next(void)

{

i++;

printf("%d\n",i); /*i 等于 5*/ other();

}

/************************************************

SOURCE FILE TWO

*************************************************/ extern int i; /* 引用 i, 定义在下面 */

/*i 在第一个源文件中 */

void other(void)

{

i++;

printf("%d\n",i); /*i 等于 6*/

}

这 个 例 子 中 的 两 个 源 文 件 包 含 i 的 三 个 外 部 说 明 。 只 有 一 项 是 “ 定 义 说明 ” , 它 为 :

int i=3;

定 义 全 局 变 量 i 并 用 初 始 值 3 对 其 进 行 初 始 化 。 在 第 一 个 源 文 件 的 顶 部

i 的 “ 引 用 ” 说 明 使 用 extern 使 该 全 局 变 量 在 这 个 文 件 中 它 的 定 义 说 明

之 前 是 可 见 的 。 在 第 二 个 源 文 件 中 i 的 引 用 说 明 使 它 在 这 个 源 文 件 中 是可 见 的 。 如 果 一 个 变 量 的 定 义 实 例 在 转 换 单 元 中 没 有 提 供 , 编 译 器 假 设有 一 个 :

extern int x;

引 用 说 明 和 一 个 定 义 引 用 :

int x=0;

出 现 在 该 程 序 的 另 外 转 换 单 元 中 。

所 有 三 个 函 数 main 、 next 和 other 执 行 同 样 的 功 能 ;它 们 将 i 增 1 ,并 打 印它 。 打 印 值 4 、 5 和 6 。

如 果 变 量 i 还 没 有 初 始 化 ,它 自 动 设 置 为 0 。 在 这 种 情 况 下 ,打 印 值 1 、 2

和 3 。 有 关 变 量 初 始 化 的 信 息 参 见 本 章 后 面 的 “ 初 始 化 ”。

内 部 层 说 明 的 存 储 类 指 示 符

你 可 以 在 内 部 层 为 变 量 说 明 使 用 任 何 四 种 存 储 类 指 示 符 终 结 符 。 当 你 从这 样 的 说 明 省 略 存 储 类 指 示 符 时 , 缺 省 的 存 储 类 是 auto 。 因 此 在 一 个 C 程 序 中 很 少 看 见 auto 关 键 字 。

auto 存 储 类 指 示 符

auto 存 储 类 指 示 符 说 明 一 个 自 动 变 量 , 即 一 个 具 有 局 部 生 存 期 的 变 量 。一 个 auto 变 量 仅 在 说 明 它 的 块 中 是 可 见 的 。 说 明 auto 变 量 包 括 初 始 化语 句 , 正 如 “ 初 始 化 ” 节 中 讨 论 的 。 由 于 具 有 auto 存 储 类 的 变 量 不 会 自动 初 始 化 , 你 可 以 在 说 明 它 们 时 显 式 对 其 初 始 化 或 者 在 该 块 的 语 句 中 赋

给 初 始 值 。 未 初 始 化 的 auto 变 量 的 值 是 不 确 定 的 ( 对 于 auto 或 register 存 储 类 的 局 部 变 量 ,如 果 给 出 一 个 初 始 化 语 句 , 那 么 每 次 进 入 其 范 围 内 都进 行 初 始 化 )。

一 个 内 部 static 变 量 ( 一 个 带 有 局 部 或 块 范 围 的 static ) 可 以 被 带 有 任 何 外部 的 或 static 项 的 地 址 初 始 化 ,而 不 能 被 带 有 其 他 auto 项 的 地 址 初 始 化 , 因 为 auto 项 地 址 不 是 一 个 常 量 。

register 存 储 类 指 示 符

Microsoft 特 殊 处 →

Microsoft C/C++ 编 译 器 并 不 赞 成 寄 存 器 变 量 的 用 户 要 求 。 但 为 了 兼 容 性 , 与 register 关 键 字 关 联 的 所 有 其 它 语 义 都 被 编 译 器 允 准 。 例 如 , 你 不 能 向一 个 寄 存 器 对 象 应 用 单 目 地 址 运 算 符 (&), 也 不 能 对 数 组 使 用 register 关键 字 。

Microsoft 特 殊 处 结 束

static 存 储 类 指 示 符

在 内 部 层 用 static 存 储 类 指 示 符 说 明 的 变 量 具 有 全 局 生 存 期 , 但 仅 在 其 说明 的 块 中 是 可 见 的 , 对 于 常 量 字 符 串 ,使 用 static 是 有 用 的 , 因 为 它 减 小 了在 经 常 调 用 的 函 数 频 繁 的 初 始 化 的 额 外 开 销 。

如 果 你 不 显 式 初 始 化 一 个 static 变 量 ,它 缺 省 初 始 化 为 0, 在 一 个 函 数 内部 ,static 导 致 分 配 存 储 并 作 为 一 个 定 义 , 内 部 静 态 变 量 提 供 的 私 有 、 持 久存 储 仅 对 单 个 函 数 是 可 见 的 。

extern 存 储 类 指 示 符

用 extern 存 储 类 指 示 符 说 明 的 变 量 是 定 义 在 外 部 层 该 程 序 的 任 何 源 文 件中 同 名 变 量 的 一 个 引 用 。 内 部 extern 说 明 用 于 使 外 部 层 变 量 定 义 在 该 块中 是 可 见 的 。 除 非 在 外 部 层 有 其 它 说 明 , 否 则 用 extern 关 键 字 说 明 的 一个 变 量 仅 在 其 说 明 的 块 是 中 可 见 的 。

例 子

这 个 例 子 说 明 了 内 部 和 外 部 层 说 明 :

#include <stdio.h> int i=1;

void other(void);

void main()

{

/* 引用 i, 定义在上面 */ extern int i;

/* 初始化值是 0,a 仅在 main 中可见 */ static int a;

/* 如果可以 ,b 存储在一个寄存器中 , */ register int b=0;

/* 缺省存储类是 auto */ int c=0;

/* 打印的值是 1,0,0,0 */ printf("%d\n%d\n%d\n%d\n",i, a ,b,c); other();

return;

}

void other(void)

{

/* 全局 i 的地址赋给指针变量 */ static int *external_i=&i;

/* i 重新定义 , 全局 i 不再可见 */ int i=16;

/* a 仅在 other 函数内可见 */ static int a=2;

a +=2;

/* 打印的值是 16,4,1 */

printf("%d\n%d\n%d\n",i,a,*external_i);

}

本 例 中 , 变量 i 的 定 义 在 外 部 层 , 并 有 初 值 1, 在 main 函 数 中 的 一 个 extern 说 明 用 来 说 明 该 外 部 层 i 的 一 个 引 用 。 static 变 量 a 缺 省 为 0 ,因 为 省 略 了初 始 化 语 句 。 调 用 printf 打 印 值 1 、 0 、 0 和 0 。

在 other 函 数 中 , 全 局 变 量 i 的 地 址 用 来 初 始 化 该 static 指 针 变 量external_i 。 这 个 工 作 因 为 全 局 变 量 有 static 生 存 期 ,其 地 址 在 程 序 执 行 中不 改 变 。 接 着 ,变 量 i 重 新 定 义 为 局 部 变 量 并 有 初 始 16 。 这 个 重 新 定 义不 影 响 外 部 层 i 的值 , 它 通 过 使 用 它 的 局 部 变 量 的 名 称 而 隐 藏 。 全 局 变 量 i 的 值 现 在 仅 在 这 个 块 中 通 过 指 针 external_i 间 接 访 问 。 试 图 把 auto 变量 i 的 地 址 赋 给 一 个 指 针 是 不 行 的 ,由 于 它 可 能 在 每 次 进 行 该 块 时 都 不 相同 。 变 量 a 作 为 一 个 static 变 量 说 明 并 初 始 化 为 2 。 这 不 会 与 main 中 的 a 冲 突 ,因 为 在 内 部 层 的 static 变 量 仅 在 它 们 说 明 的 块 中 是 可 见 的 。

变 量 a 增 大 2, 给 出 4 作 为 结 果 。 如 果 other 函 数 在 同 一 程 序 中 再 次 调 用 ,a 的 初 始 值 为 4 。 内 部 static 变 量 在 程 序 退 出 ,然 后 重 新 进 入 说 明 它 们 的 块中 时 保 存 它 们 的 值 。

函 数 说 明 的 存 储 类 指 示 符

你 可 以 在 函 数 说 明 中 使 用 static 或 extern 存 储 类 指 示 符 。 函 数 总 是 有 全局 生 存 期 。

Microsoft 特 殊 处 →

在 内 部 层 的 函 数 说 明 和 外 部 层 的 函 数 说 明 具 有 相 同 的 含 义 。 这 意 味 着 一

个 函 数 从 说 明 的 点 到 该 转 换 单 元 的 其 余 部 分 中 都 是 可 见 的 , 甚 至 在 局 部范 围 中 说 明 亦 如 此 。

Microsoft 特 殊 处 结 束

函 数 的 可 见 性 规 则 有 点 不 同 于 变 量 的 可 见 性 规 则 , 如 下 :

  • 说 明 为 static 的 一 个 函 数 仅 在 定 义 它 的 源 文 件 中 是 可 见 的 。 在 相同 源 文 件 中 的 函 数 可 以 调 用 static 函 数 , 但 在 其 它 源 文 件 中 不 能 用其 名 称 直 接 访 问 。 你 可 以 用 相 同 的 名 称 在 不 同 的 源 文 件 中 没 有 冲 突地 说 明 另 一 个 static 函 数 。

  • 以 extern 说 明 的 函 数 在 该 程 序 的 所 有 源 文 件 中 都 是 可 见 的 ( 除 非 你以 后 重 新 说 明 这 样 的 一 个 函 数 为 static) 。 任 何 函 数 可 以 调 用 一 个extern 函 数 。

  • 省 略 存 储 类 指 示 符 的 函 数 说 明 缺 省 是 extern 的 。

Microsoft 特 殊 处 →

Microsoft 允 许 重 新 定 义 一 个 extern 标 识 符 为 static 。

Microsoft 特 殊 处 结 束

指 示 符

在 说 明 中 类 型 指 示 符 定 义 一 个 变 量 或 函 数 说 明 的 类 型 。语 法

类 型 指 示 符 :

void

char short int long float double signed

unsigned

结构或联合指示符枚 举 指 示 符 typedef 名称

signed cha r 、 signed in t 、 signed short int 和 signed long int 类 型 与 它 们 的

unsigned 对 应 部 分 以 及 enum 都 称 之 为“ 整 型 ”。float 、double 和 long double 类 型 指 示 符 被 称 为 “ 浮 点 型 ”。 你 可 以 在 一 个 变 量 或 函 数 说 明 中 使 用 任何 整 型 或 浮 点 型 。 如 果 在 一 个 说 明 中 没 有 提 供 一 个 类 型 指 示 符 , 把 它 作为 in t。

任 选 关 键 字 signed 和 unsigned 可 以 位 于 或 紧 跟 任 何 整 型 ,除 enum 之 外 , 都 可 以 单 独 作 为 类 型 指 示 符 , 这 种 情 况 下 , 它 们 分 别 作 为 signed int 和unsigned in t。 当 单 独 使 用 时 ,关 键 字 int 假 设 为 signed 。 当 单 独 使 用 时 , 关键 字 long 和 short 作 为 long int 和 short in t 。

枚 举 类 型 考 虑 为 基 本 类 型 。 枚 举 类 型 的 类 型 指 示 符 在 本 章 后 面 的 “ 枚 举说 明 ” 中 讨 论 。

关 键 字 void 有 三 种 用 途 :指 出 一 个 函 数 返 回 值 、 指 出 一 个 不 接 受 参 量 的函 数 的 参 量 类 型 表 以 及 指 出 一 个 非 指 定 的 类 型 的 指 针 。 你 可 以 使 用 void 类 型 说 明 没 有 返 回 值 的 函 数 或 说 明 一 个 未 指 定 类 型 的 指 针 。 有 关 void 出 现 在 一 个 函 数 名 称 之 后 的 括 号 中 的 信 息 ,参 见 第 6 章 “ 函 数 ” 中 的“ 参量 ” 。

Microsoft 特 殊 处 →

现 在 的 类 型 检 测 是 ANSI 兼 容 的 , 这 意 味 着 类 型 short 和 int 是 不 同 的 类型 。 例 如 , 在 Microsoft C 编 译 器 中 的 重 新 定 义 被 以 前 的 编 译 器 版 本 接 受 。int myfunc();

short myfunc();

下 面 的 例 子 还 产 生 一 个 关 于 不 同 类 型 之 间 间 接 赋 值 的 警 告 :

int *pi; short *ps;

ps=pi; /* 现在产生警告 */

M icrosoft C 编译器也产生关于不同符号的警告 ,例 如 :

signed int *pi; unsigned int *pu;

pi=pu; /* 现在产生警告 */

类型 void 表达式求值是为了副作用。你不能以任何方式使用 ( 不存在的 ) 一个有类型 void 的表达式的值 , 也不能把一个 void 表达式 (隐含或显式转换 )转 换 成 除 void

之外的任何类型。

如 果 你 在 需 要 一 个 void 表 达 式 的 上 下 文 中 使 用 一 个 其 它 类 型 的 表 达 式 ,

它 的 值 被 丢 弃 。

为 了 与 ANSI 规 格 一 致 ,void ** 不 能 用 作 int ** 。 只 有 void * 可 以 用 作 一个 未 指 定 类 型 的 一 个 指 针 。

Microsoft 特 殊 处 结 束

你 可 以 用 typedef 说 明 建 立 另 外 的 类 型 指 示 符 ,正 如 在 本 章 后 面 “ typedef

说 明 ”中 描 述 的 有 关 每 种 类 型 的 尺 寸 的 信 息 ,请 参 见“ 基 本 类 型 的 存 储 ”。

数 据 类 型 指 示 符 和 等 价 者

本 书 通 常 使 用 表 3.1 中 列 出 的 类 型 指 示 符 的 格 式 , 而 不 是 长 格 式 , 它 假 设

char 类 型 缺 省 是 有 符 号 的 。 因 此 ,在 本 书 中 ,char 等 价 于 signed cha r。

表 3.1 类 型 指 示 符 和 等 价 者

类型指示符 等价者

signed char 1 char

signed int s igned , int

signed short int short, signed short

signed long int long, signed long

unsigned char -

unsigned int unsigned

unsigned short int unsigned short

续 表

类 型 指 示 符 等 价 者

unsigned long int unsigned long

float -

long double 2 -

1. 当你使 char 类型缺省为无符号的 ( 通过指定 /J 编译器选项 ), 你不能简写 signed char 为 char 。2 . 在 32 位操作系统中 ,Microsoft C 编译器把 long double 映射成 double。

Microsoft 特 殊 处 →

你 可 以 指 定 /J 编 译 器 选 项 改 变 缺 省 char 类 型 从 有 符 号 的 到 无 符 号 的 。当 这 个 任 选 项 起 作 用 时 ,char 与 unsigned char 相 同 , 你 必 须 使 用 signed 关键 字 说 明 一 个 有 符 号 字 符 值 。 如 果 一 个 char 值 显 式 说 明 为 有 符 号 的 ,/J 选 项 对 它 没 影 响 , 当 宽 度 变 为 int 类 型 时 其 值 进 行 符 号 扩 充 。 当 宽 度 变 为ing 类 型 时 ,char 类 型 进 行 0 扩 充 。

Microsoft 特 殊 处 结 束

类 型 修 饰 符

类 型 修 饰 符 给 一 个 标 识 符 两 种 属 性 之 一 。 const 类 型 修 饰 符 说 明 一 个 对象 是 不 可 修 改 的 。 voatile 类 型 说 明 一 个 项 , 其 值 在 有 时 超 出 它 出 现 的 程序 的 范 围 例 如 并 发 执 行 线 程 时 可 以 改 变 。

两 个 类 型 修 饰 符 const 和 volatile 在 一 个 说 明 中 仅 出 现 一 个 。 类 型 修 饰符 可 以 与 任 何 类 型 指 示 符 一 起 使 用 , 但 它 们 不 能 出 现 在 多 项 说 明 中 的 第

一 个 逗 号 之 后 。

例 如 , 以 下 说 明 是 合 法 的 :

typedef volatile int VI; const int ci;

以 下 说 明 不 是 合 法 的 :

typedef int *i, volatile *vi; float f, const cf;

类 型 修 饰 符 仅 当 在 表 达 式 中 作 为 l 值 访 问 标 识 符 时 是 相 关 的 。 有 关 l 值

和 表 达 式 的 信 息 参 见 第 4 章 “ 表 达 式 和 赋 值 ” 的 “ L 值和 R 值 表 达 式 ”。

语法

类型修饰符 :

const volatile

如下是合法的 const 和 volatile 说明 :

int const *p_ci; /* 常量 int 的指针 */

int const (*p_ci), /* 常量 int 的指针 */ int *const cp_i; /* int 的常量指针 */

int (*const cp_i); /* int 的常量指针 */ int volatile vint; /* volatile 整数 */

如 果 一 个 数 组 类 型 的 规 格 包 括 类 型 修 饰 符 , 被 修 饰 是 其 元 素 , 而 不 是 数 组

类 型 。 如 果 一 个 函 数 类 型 的 规 格 包 括 修 饰 符 , 其 行 为 是 不 确 定 的 。 volatile

和 const 都 不 影 响 对 象 的 值 的 范 围 或 算 术 属 性 。

这 里 列 出 如 何 使 用 const 和 volatile:

  • const 关 键 字 可 以 用 于 修 饰 任 何 基 本 的 或 集 合 类 型 , 或 者 任 何 类 型 的对 象 的 指 针 或 者 一 个 typedef 。 如 果 一 个 项 仅 用 const 类 型 修 饰 符说 明 , 它 的 类 型 作 为 const int 。 一 个 const 变 量 可 以 初 始 化 或 放在 一 个 只 读 存 储 区 域 中 。 const 关 键 字 对 于 说 明 const 的 指 针 是 有用 的 , 因 为 这 需 要 该 函 数 不 以 任 何 方 式 改 变 该 指 针 。

  • 编 译 器 假 设 在 程 序 的 任 何 地 方 , 一 个 volatile 变 量 可 以 通 过 使 用 或修 改 它 的 值 的 未 知 进 程 来 访 问 。 因 此 , 不 管 命 令 行 指 定 的 优 化 , 必 须生 成 每 个 赋 值 的 代 码 或 一 个 volatile 变 量 引 用 的 代 码 , 甚 至 它 的 出现 没 有 作 用 亦 如 此 。

如 果 单 独 使 用 volatile, 假 设 是 int 。 volatile 类 型 指 示 符 用 于 提供 对 特 定 存 储 器 位 置 可 靠 的 访 问 。 对 于 可 以 通 过 信 号 处 理 器 , 通 过并 发 执 行 程 序 或 通 过 特 定 硬 件 例 如 存 储 器 映 射 的 I/O 控 制 寄 存 器 来访 问 或 改 变 的 数 据 对 象 使 用 volatile 。 你 可 以 为 生 存 期 声 明 一 个 变量 为 volatile, 或 者 造 型 单 个 引 用 为 volatile 。

  • 一 个 项 可 以 是 const 和 volatile, 在 这 种 情 况 下 该 项 不 会 由 它 自 己的 程 序 合 理 修 改 , 但 可 以 由 一 些 异 步 进 程 修 改 。

说 明 符 和 变 量 说 明

本 章 其 余 部 分 描 述 了 变 量 类 型 的 格 式 和 含 义 , 其 总 结 在 如 下 表 中 。 特 别地 ,下 面 的 几 节 解 释 如 何 说 明 如 下 内 容 。

变量类型 说明

简单变量 具有整型或浮点型的单个值变量

数组 由相同类型的元素集合组成的变量

指针 指 向 其 它 变 量 的 变 量 , 包 含 变 量 的 位 置 , 以地址格式存储代替值

枚举变量 具 有 整 型 的 简 单 变 量 , 保 存 一 个 命 名 的 整数常量集合中的一个值

结构 由具有不同类型的值的集合组成的变量

联合 由 同 一 存 储 空 间 中 几 个 不 同 类 型 的 值 组 成的变量

一 个 说 明 符 是 指 出 引 入 到 程 序 中 的 名 称 的 一 个 说 明 ,它 可 以 包 括 修 饰 符 ,

例 如 *( 指 针 ) 和 任 何 M icrosoft 调 用 约 定 的 关 键 字 。

Microsoft 特 殊 处 → 在 说 明 符 中 :

__ declspec(thread) char *var;

char 是 类 型 指 示 符 , _ _declspec 和 * 是 修 饰 符 ,var 是 标 识 符 的 名 称 。

Microsoft 特 殊 处 结 束

你 可 以 使 用 说 明 符 说 明 指 定 类 型 值 的 数 组 、 指 定 类 型 值 的 指 针 和 指 定 类型 返 回 值 的 函 数 。 出 现 在 数 组 和 指 针 说 明 中 的 说 明 符 在 本 章 后 面 描 述 。语法

说明符 :

指针 opt 直接说明符

直接说明符 :

标识符

(说明符 )

直接说明符 [ 常量表达式 opt ]

直接说明符 ( 参数类型表 ) 直接说明符 ( 标识符表 opt )

指针 :

  • 类型修饰符表 opt

  • 类型修饰符表 opt 指针类型修饰符表 :

类型修饰符

类型修饰符表 类型修饰符

注 意 : 有 关 一 个 说 明 符 的 引 用 语 法 , 参 见 本 章 开 头 的 “ 说 明 概 述 ” 中 的 说明 的 语 法 或 参 见 本 卷 后 面 的 附 录 A “ C 语 言 语 法 总 结 ”。

当 一 个 说 明 符 由 一 个 非 修 饰 符 的 标 识 符 组 成 时 , 说 明 的 项 有 一 个 基 本 类型 。 如 果 一 个 星 号 (*) 出 现 在 一 个 标 识 符 的 左 边 , 该 类 型 修 改 为 一 个 指 针类 型 。 如 果 该 标 识 符 紧 跟 方 括 号 [], 该 类 型 修 改 为 一 个 数 组 类 型 。 有 关 说明 中 优 先 级 解 释 的 更 多 信 息 , 参 见 本 章 后 面 的 “ 解 释 更 复 杂 的 说 明 符 ”。每 个 说 明 符 至 少 说 明 一 个 标 识 符 。 一 个 说 明 符 必 须 包 括 一 个 完 整 说 明 的类 型 指 示 符 。 该 类 型 指 示 符 给 出 了 一 个 数 组 类 型 的 元 素 的 类 型 、 指 针 类型 所 指 对 象 的 类 型 或 者 一 个 函 数 的 返 回 值 。

数 组 和 指 针 说 明 在 本 章 后 面 有 更 详 细 的 讨 论 。 如 下 例 子 说 明 几 种 简 单 的

说 明 符 格 式 :

int list[20] /* 说明一个名称为 list,20 个整数的数组 */ char *cp; /* 说明一个 char 值的指针 */

double func(void) /* 说明一个名称为 func 的函数 ,没有参量 , 返回值为一个 double

值 */

int *aptr[10]; /* 说明一个有 10 个指针的数组 */

Microsoft 特殊处→

M icrosoft C 编译器不限制修饰一个算术、结构或联合类型的说明符的个数。该个数仅受限于可用的存储器空间。

Microsoft 特殊处结束

简 单 变 量 说 明

简 单 变 量 的 说 明 是 直 接 说 明 符 的 最 简 单 的 格 式 , 它 指 出 变 量 的 名 称 和 类型 ,它 还 指 出 该 变 量 的 存 储 类 和 数 据 类 型 。

在 变 量 说 明 中 需 要 存 储 类 或 类 型 ( 或 两 者 ), 没 有 类 型 的 变 量 ( 例 如 var;) 产生 警 告 。

语 法 说明符 :

指针 opt 直接说明符

直接说明符 :

标识符标识符 :

非数字

标识符 非数字标识符 数字

对 于 算 术 、 结 构 、 联 合 、 枚 举 和 void 类 型 以 及 由 typedef 命 名 表 示 的 类

型 , 在 一 个 说 明 中 可 以 使 用 简 单 说 明 符 , 因 为 该 类 型 指 示 符 提 供 所 有 类 型信 息 。 指 针 、 数 组 和 函 数 类 型 需 要 更 复 杂 的 说 明 符 。

你 可 以 使 用 一 个 标 识 符 表 , 标 识 符 之 间 用 逗 号 分 隔 , 以 便 在 同 一 说 明 中 指出 几 个 变 量 。 在 该 说 明 中 定 义 所 有 变 量 具 有 相 同 的 基 本 类 型 。 例 如 :

int x,y; /* 说明两个 int 类型的简单变量 */ int const z=1; /* 说明类型为 int 的 变 量 值 */

变 量 x 和 y 为 了 一 个 特 殊 实 现 保 存 int 类 型 定 义 的 集 中 的 任 何 值 。 简 单

对 象 z 初 始 化 为 1, 并 且 是 不 可 修 改 的 。 如 果 z 的 说 明 是 一 个 非 初 始 化 的静 态 变 量 或 具 有 文 件 范 围 , 它 接 受 一 个 初 始 值 0 并 也 是 不 可 修 改 的 。unsigned long reply,flag; /* 说 明 两 个 命 名 为 reply 和 flag 的 变 量 */

在 这 个 例 子 中 , 两 个 变 量 reply 和 flag 都有 unsigned long 类 型 并 保 存 无 符号 整 数 值 。

枚 举 说 明

一 个 枚 举 是 由 一 个 命 名 的 整 数 常 量 组 成 的 。 一 个 枚 举 类 型 说 明 给 出 了 枚举 标 志 的 名 称 ( 任 选 的 )并 定 义 命 名 的 整 数 标 识 符 的 集 合 ( 称 为 “ 枚 举 集 ”、“ 枚 举 常 量 ”、“ 枚 举 器 ” 或 “ 成 员 ” )。 一 个 具 有 枚 举 类 型 的 常 量 存 储该 类 型 定 义 的 枚 举 集 的 值 之 一 。

enum 类 型 的 变 量 可 以 用 在 指 标 表 达 式 中 , 作 为 所 有 算 术 和 关 系 运 算 符 的操 作 数 , 枚 举 提 供 了 替 代 #define 预 处 理 器 命 令 的 另 一 种 方 法 ,利 用 它 为 你生 成 值 和 遵 守 正 常 范 围 规 则 的 优 点 。

在 ANSI C 中 , 定 义 一 个 枚 举 常 量 的 值 的 表 达 式 总 是 具 有 int 类 型 ,因 此 与一 个 枚 举 变 量 关 联 的 存 储 是 单 个 int 值 需 要 的 存 储 。 一 个 枚 举 常 量 或 一个 枚 举 类 型 的 值 可 以 用 在 C 语 言 允 许 一 个 整 数 表 达 式 使 用 的 任 何 地 方 。语法

enum 指示符 :

enum 标识符 opt{ 枚举器表 } enum 标识符

可 选 标 识 符 命 名 由 枚 举 器 表 定 义 的 枚 举 类 型 。 这 个 标 识 符 经 常 称 为 该 表

指 定 的 枚 举 的 “ 标 志 ”。 一 个 类 型 指 示 符 的 格 式 为 :

enum 标 识 符 { 枚 举 器 表 }

说 明 该 标 识 符 是 由 枚 举 器 表 指 定 的 枚 举 的 标 志 。该 枚 举 器 表 定 义 了 该“ 枚举 器 内 容 ”。 该 枚 举 器 表 在 下 面 详 细 描 述 。

如 果 一 个 标 志 的 说 明 是 可 见 的 , 后 续 使 用 该 标 志 而 省 略 枚 举 器 表 的 说 明指 出 以 前 说 明 的 枚 举 的 类 型 。 该 标 志 必 须 指 的 是 一 个 定 义 的 枚 举 类 型 , 该 枚 举 类 型 必 须 在 当 前 范 围 中 。 因 为 枚 举 类 型 定 义 在 其 它 地 方 , 该 枚 举器 表 不 出 现 在 这 个 说 明 中 。 从 枚 举 派 生 的 类 型 的 说 明 和 枚 举 类 型 的typedef 说 明 可 以 在 该 枚 举 类 型 定 义 之 前 使 用 该 枚 举 标 志 。

语法

枚举器表 :

枚举器

枚举器表 ,枚举器枚举器 :

枚举常量

枚举常量 = 常量表达式枚举常量 :

标识符

在 枚 举 器 表 中 的 每 个 枚 举 器 常 量 命 名 该 枚 举 集 的 值 。 缺 省 地 , 第 一 个 枚举 常 量 与 值 0 关 联 , 该 表 中 的 下 一 个 枚 举 常 量 与 值 ( 常 量 表 达 式 +1) 的 值 关联 , 除 非 你 显 式 地 将 其 与 其 它 值 关 联 。 一 个 枚 举 常 量 的 名 称 等 价 于 它 的值 。

你 可 以 使 用 枚 举 常 量 = 常 量 表 达 式 来 覆 盖 值 的 缺 省 序 列 。 因 此 , 如 果 枚 举常 量 = 常 量 表 达 式 出 现 在 该 枚 举 器 表 中 ,该 枚 举 常 量 与 常 量 表 达 式 给 定 的值 关 联 。 该 常 量 表 达 式 必 须 有 int 类 型 且 可 以 为 负 数 。

如 下 规 则 应 用 于 一 个 枚 举 集 的 成 员 :

  • 一 个 枚 举 集 可 以 包 含 重 复 的 常 量 值 。 例 如 , 你 可 以 用 两 个 不 同 的 标识 符 与 0 关 联 , 它 们 是 同 一 个 集 中 , 可 能 是 mull 和 zero 。

  • 枚 举 集 中 的 标 识 符 必 须 不 同 于 同 一 范 围 中 具 有 相 同 可 见 性 的 其 它 标识 符 , 包 括 普 通 变 量 名 称 和 其 它 枚 举 表 中 的 标 识 符 。

  • 枚 举 标 志 遵 守 一 般 范 围 规 则 , 它 们 必 须 不 同 于 相 同 可 见 性 的 其 它 枚举 、 结 构 和 联 合 标 志 。

例子

这些例子说明了枚举的说明 :

enum DAY /* 定义一个枚举类型 */

{

saturday,/* 命名 day 并说明具有该类型的变量 workday */ sunday=0,

monday, tuesday,

wednesday, /*wednesday 与 3 关联 */

thursday, fr iday

} workday;

缺 省 地 值 0 与 saturday 关 联 。 标 识 符 sunday 显 式 设 置 为 0 。 余 下 的 标 识符 根 据 缺 省 给 出 1 到 5 的 值 。 在 以 下 例 子 中 ,一 个 集 DAY 的 值 赋 给 变 量today:

enum DAY today=wednesday;

注 意 , 枚 举 常 量 的 名 称 用 作 赋 值 。 由 于 DAY 枚 举 类 型 是 以 前 说 明 的 ,只有 枚 举 标 志 DAY 是 必 要 的 。

为 了 显 式 地 把 一 个 整 数 值 赋 给 一 个 枚 举 的 数 据 类 型 的 变 量 , 使 用 一 个 类型 造 型 :

workday=(enum DAY) (day_value-1);

这 个 造 型 在 C 中 推 荐 ,但 是 不 需 要 的 。

enum BOOLEAN/* 说明一个称为 BOOLEAN 的枚举数据类型 */

{

false,/*false=0,true=1 */ true

};

enum BOOLEAN end_flag,match_flag; /* BOOLEAN 类型的两个变量 */

这个说明也可以指定为 :

enum BOOLEAN {false,true} end_flag,match_flag;\

enum BOOLEAN {fa lse,true} end_flag; enum BOOLEAN match_flag;

使用这三个变量的例子如下 :

if (match_flag == false)

{

.

. /* 语句 */

.

}

end_flag = true;

可 以 说 明 未 命 名 的 枚 举 器 数 据 类 型 。 省 略 数 据 类 型 的 名 称 , 但 可 以 说 明变 量 。 变 量 response 是 这 样 定 义 的 类 型 的 变 量 :

enum {yes, no} response;

结 构 说 明

一 个 “ 结 构 说 明 ” 命 名 一 个 类 型 并 指 定 具 有 不 同 类 型 变 量 值 ( 称 为 结 构的 “ 成 员 ” 或 域 ) 的 序 列 。 一 个 称 为 “ 标 志 ” 的 任 选 标 识 符 给 出 结 构 类型 的 名 称 , 可 以 用 在 后 面 对 结 构 类 型 的 引 用 中 , 一 个 结 构 类 型 的 变 量 保 存该 类 型 定 义 的 整 个 序 列 。 在 C 中 结 构 类 似 于 其 它 语 言 中 众 所 周 知 的“ 记录 ” 。

语法

结构或联合标识符 :

结构或联合标识符 opt { 结构说明表 } 结构或联合标识符

结构或联合 :

struct union

结构说明表 :

结构说明

结构说明表 结构说明结构的内容定义为 :

结构说明 :

指示符修饰符表 结构说明符表指示符修饰符表 :

类型指示符 指 示 符 修 饰 符 表 opt

类型修饰符 指 示 符 修 饰 符 表 opt

结构说明表 :

结构说明符

结构说明符表 ,结构说明符结构说明符 :

说明符

一 个 结 构 类 型 的 说 明 不 为 一 个 结 构 设 置 另 外 空 间 , 它 只 是 一 个 模 块 , 便 于后 面 说 明 结 构 变 量 。

前 面 定 义 的 标 识 符 ( 标 志 ) 可 以 用 于 指 向 其 它 地 方 定 义 的 一 个 结 构 类 型 。在 这 种 情 况 下 , 结 构 说 明 表 不 能 重 复 直 到 它 的 定 义 是 可 见 的 。 结 构 的 指针 的 说 明 和 结 构 类 型 的 typedef 可 以 在 该 结 构 类 型 被 定 义 之 前 使 用 该 结构 标 志 。 但 必 须 在 其 任 何 域 的 尺 寸 的 实 际 使 用 之 前 遇 到 该 结 构 定 义 。 这是 类 型 和 类 型 标 志 的 不 完 整 定 义 。 为 了 完 成 这 个 定 义 , 必 须 在 相 同 范 围的 后 面 出 现 一 个 类 型 定 义 。

结 构 说 明 表 指 出 结 构 成 员 的 类 型 和 名 称 。 一 个 结 构 说 明 表 参 量 包 含 一 个或 多 个 变 量 或 位 域 说 明 。

在 结 构 说 明 表 中 说 明 的 每 个 变 量 定 义 为 该 结 构 类 型 的 一 个 成 员 , 在 结 构说 明 表 中 的 变 量 说 明 和 本 章 讨 论 的 其 它 变 量 的 说 明 具 有 相 同 的 格 式 , 除了 该 说 明 不 能 包 含 存 储 类 指 示 符 或 初 始 化 语 句 外 , 该 结 构 成 员 可 以 具 有除 void 之 外 的 任 何 类 型 、 一 个 不 完 整 的 类 型 或 一 个 函 数 类 型 。

一 个 成 员 不 能 说 明 成 为 具 有 包 含 该 成 员 的 结 构 的 类 型 , 但 一 个 成 员 可 以说 明 成 为 包 含 该 成 员 的 结 构 的 指 针 , 该 结 构 类 型 有 一 个 标 志 。 这 允 许 你

建 立 结 构 链 表 。

结 构 与 其 它 标 识 符 遵 循 同 样 的 范 围 规 则 。 结 构 标 识 符 必 须 不 同 于 具 有 相同 可 见 性 的 其 它 结 构 、 联 合 和 枚 举 标 志 。

在 结 构 说 明 表 中 的 每 个 结 构 说 明 在 该 表 中 必 须 是 唯 一 的 。 但 一 个 结 构 说明 表 中 的 标 识 符 名 称 不 必 与 其 它 普 通 变 量 名 或 其 它 结 构 说 明 表 中 的 标 识符 相 区 分 。

通 过 在 文 件 范 围 层 说 明 ,还 可 以 访 问 嵌 套 的 结 构 。 例 如 , 给 出 这 样 的 说 明 :

struct a

{

int x; struct b

{

int y

} var2;

} var1;

如 下 说 明 都 是 合 法 的 :

struct a var3; struct b var4;

例 子

这 些 例 子 说 明 了 结 构 的 说 明 :

struct employee/* 定义一个命名为 temp 的结构变量 */

{

char name[20]; int id;

long class;

} temp;

employee 结 构 有 三 个 成 员 ,nam e、 id 和 class 。 name 成 员 是 一 个 20 个 元素 的 数 组 ;id 和 class 分 别 是 int 和 long 类 型 的 简 单 成 员 。标 识 符 employee 是 结 构 标 识 符 。

struct employee student, faculty, staff;

这 个 例 子 定 义 了 三 个 结 构 变 量 :student、 faculty 和 staff。 每 个 结 构 都 有三 个 成 员 的 相 同 表 。 这 些 成 员 被 说 明 为 有 结 构 类 型 employee ,定 义 在 前面 的 例 子 中 :

struct/* 定义一个无名的结构和 a*/

{

float x,y;

} complex; /* 结构变量命名为 complex*/

complex 结构具有两个 float 类 型 的 成 员 x 和 y, 该结构类型没有标志 ,因此是未命名或无名的。

struct sample /* 定义一个命名为 x 的结构 */

{

char c; float *pf;

struct sample *next;

} x;

该 结 构 开 头 两 个 成 员 是 一 个 char 变 量 和 一 个 float 值 的 指 针 。 第 三 个 成员 next 说 明 为 定 义 的 结 构 类 型 (sample )的 指 针 。

在 不 需 要 命 名 的 标 志 是 无 名 结 构 是 有 用 的 。 这 是 一 个 说 明 定 义 所 有 结 构实 例 的 情 况 。

例如 :

struct

{

int x; int y;

} mystruct;

嵌入的结构通常是无名的。

struct somestruct

{

struct /* 无名的结构 */

{

int x,y;

} point; int type;

} w;

Microsoft 特 殊 处 →

编 译 器 允 许 一 个 无 尺 寸 的 或 0 尺 寸 的 数 组 作 为 一 个 结 构 的 最 后 成 员 , 如

果 一 个 常 量 数 组 的 尺 寸 在 不 同 情 况 下 也 不 同 时 , 这 是 有 用 的 。 这 样 的 一个 说 明 如 下 :

struct 标 识 符

{

说 明 集

类 型 数 组 名 称 [];

};

无 尺 寸 的 数 组 只 能 作 为 一 个 结 构 的 最 后 成 员 。 包 含 无 尺 寸 的 数 组 说 明 的结 构 可 以 嵌 套 在 其 它 结 构 中 , 以 及 在 包 含 它 的 结 构 中 没 有 更 多 成 员 需 要说 明 。 不 允 许 这 样 结 构 的 数 组 , 当 sizeof 运 算 符 应 用 于 这 种 类 型 的 变 量或 这 个 类 型 本 身 时 , 该 数 组 的 尺 寸 假 设 为 0 。

在 该 结 构 是 另 一 个 结 构 或 联 合 的 成 员 时 , 没 有 一 个 说 明 符 也 可 以 指 定 该结 构 说 明 。 域 名 称 提 升 到 包 括 它 的 结 构 中 。 例 如 , 一 个 较 少 命 令 的 结 构如 下 :

struct s

{

float y; struct

{

int a,b,c;

};

char str[10];

} *p_s;

.

.

.

p_s->b = 100; /*s 结构中一个域的引用 */

有 关 结 构 引 用 的 信 息 , 参 见 第 4 章 “ 表 达 式 和 赋 值 ” 中 的 “ 结 构 和 联 合成 员 ”。

Microsoft 特 殊 处 结 束

位 域

除 了 说 明 一 个 结 构 或 联 合 的 成 员 外 , 一 个 结 构 说 明 符 还 可 以 指 定 位 的 个数 , 称 为 一 个 位 域 , 其 长 度 由 说 明 符 的 域 名 后 的 冒 号 来 设 置 。 一 个 位 域 解释 为 一 个 整 型 。

语 法

结 构 说 明 符 :

说 明 符

类 型 指 示 符 说 明 符 opt:常 量 表 达 式

该 常 量 表 达 式 指 出 域 的 位 域 。 说 明 符 的 类 型 指 示 符 必 须 是 unsigned in t、signed int 或 int, 且 常 量 表 达 式 必 须 是 非 负 整 数 。 如 果 其 值 为 0, 该 说 明 不是 说 明 符 。 不 允 许 有 位 域 的 数 组 、 位 域 的 指 针 和 返 回 位 域 的 函 数 。 任 选说 明 符 命 名 位 域 。位 域 只 能 说 明 为 一 个 结 构 的 一 部 分 。取 地 址 运 算 符 (&) 不 能 应 用 于 位 域 的 组 成 成 分 。

无 名 的 位 域 不 能 被 引 用 , 它 们 的 内 容 在 运 行 时 是 不 可 预 料 的 。 它 们 为 了赋 值 目 的 可 以 用 作 “ 哑 元 ” 域 。 一 个 其 宽 度 指 定 为 0 的 无 名 位 域 保 证 在该 结 构 说 明 表 中 紧 跟 它 的 成 员 从 一 个 int 边 界 开 始 存 储 。

位 域 也 必 须 足 够 长 以 便 包 含 位 模 式 ,例 如 ,这 样 的 两 个 语 句 是 非 法 的 :

short a:17, /* 非法的 !*/ int long y:33/* 非法的 !*/

如 下 例 子 定 义 一 个 二 维 结 构 数 组 并 命 名 为 screen:

struct

{

unsigned short icon : 8; unsigned short color : 4; unsigned short underline : 1; unsigned short blink : 1;

} screen[25][80];

该 数 组 包 含 2000 个 元 素 ,每 个 元 素 是 一 个 包 含 四 个 位 域 成 员 :icon 、color、underline 和 blink 的 结 构 。 每 个 结 构 的 尺 寸 是 两 个 字 节 。

位 域 与 整 数 类 型 具 有 相 同 的 语 义 。 这 意 味 着 一 个 表 达 式 中 使 用 一 个 位 域的 方 式 与 相 同 基 本 类 型 的 变 量 使 用 的 方 式 完 全 相 同 , 而 不 论 在 位 域 中 有多 少 位 。

Microsoft 特 殊 处 →

以 int 定 义 的 位 域 处 理 为 有 符 号 的 。 一 个 M icrosoft 扩充 ANSI C 标 准 允许 位 域 有 char 和 long 类型 (signed 和 unsigned) 。具 有 基 本 类 型 long 、short

或 char(signed 或 unsigned) 的 无 名 的 位 域 强 制 赋 给 适 合 于 该 基 本 类 型 的边 界 。

在 一 个 整 数 从 最 低 有 效 数 字 位 到 最 高 有 效 数 字 位 都 分 配 位 域 , 在 以 下 代码 中 :

struct mybitfields

{

unsigned short a : 4; unsigned short b : 5; unsigned short c : 7;

} test;

void main(void)

{

test.a=2; test.b=31; test.c=0;

}

这 些 位 排 列 如 下

00000001 11110010

cccccccb bbbbaaaa

由 于 8086 处 理 器 簇 在 高 位 字 节 之 前 存 储 整 数 的 低 位 字 节 , 上 面 的 整 数

0x01F2 在 物 理 存 储 器 中 先 存 储 0xF2 ,接 着 是 0x01 。

Microsoft 特 殊 处 结 束

结 构 的 存 储 和 赋 值

Microsoft 特 殊 处 →

结 构 成 员 以 它 们 说 明 的 顺 序 存 储 : 第 一 个 成 员 具 有 最 低 的 存 储 器 地 址 , 最后 的 成 员 具 有 最 高 的 存 储 器 地 址 。

每 个 数 据 对 象 有 一 个 对 齐 要 求 。 对 于 结 构 , 该 要 求 是 它 的 成 员 最 大 的 要求 值 。 每 个 对 象 分 配 一 个 偏 移 量 以 便 :

偏移量 % 对齐要求 == 0

如 果 整 数 类 型 具 有 相 同 的 尺 寸 , 且 如 果 下 一 个 位 域 适 合 于 当 前 分 配 单 元且 通 过 该 位 域 的 公 共 对 齐 要 求 的 统 一 而 没 有 边 界 交 叉 , 则 调 整 位 域 为 相同 的 1 、 2 或 4 字 节 分 配 单 元 。

为 了 节 省 空 间 或 使 现 存 数 据 结 构 一 致 , 你 可 以 更 紧 凑 或 更 松 散 地 存 储 结构 。 /Zp[ n ] 编 译 器 选 项 和 #pragma pack 控 制 结 构 数 据 如 何 “ 紧 凑 ” 进 入存 储 器 。 当 你 使 用 /Zp[ n ] 选 项 时 , 这 里 n 是 1 、 2 、 4 、 8 或 16, 第 一 个 结 构成 员 之 后 的 每 个 结 构 成 员 存 储 一 个 字 节 边 界 , 该 边 界 是 域 的 对 齐 要 求 或紧 凑 尺 寸 (n)。 这 里 是 很 小 的 , 表 示 成 一 个 公 式 , 字 节 边 界 是 :

min(n,sizeof( 项 ))

这 里 的 n 是 /Zp[ n ] 选 项 表 示 的 紧 凑 尺 寸 , 项 是 结 构 成 员 。 缺 省 的 紧 凑 尺 寸是 /Zp8 。 为 了 使 用 pack 编 译 指 示 以 指 出 紧 凑 ,该 紧 凑 是 非 命 令 行 中 为 一个 特 定 结 构 所 指 的 紧 凑 ,给 出 pack 编 译 指 示 ,这 里 紧 凑 尺 寸 在 该 结 构 之 前取 值 为 1 、 2 、 4 、 8 或 16 。 为 了 在 命 令 行 重 新 安 装 该 紧 凑 ,指 出 不 带 参 量

的 pack 编 译 指 示 。

对 于 Microsoft C 编 译 器 , 位 域 缺 省 为 long 尺 寸 。 结 构 成 员 在 该 类 型 的 尺寸 或 /Zp [n ] 尺 寸 上 对 齐 , 这 里 是 较 小 的 。 缺 省 尺 寸 为 4 。

Microsoft 特 殊 处 结 束

联 合 说 明

一 个 “ 联 合 说 明 ” 指 出 变 量 值 的 集 合 ,它 是 任 选 的 , 一 个 标 志 命 名 该 联 合 。该 变 量 值 称 为 联 合 的 成 员 , 可 以 有 不 同 类 型 , 联 合 类 似 于 其 它 语 言 中 的“ 可变 记 录 ”。

语法

结构或联合指示符 :

结构或联合 指示符 opt { 结构说明表 } 结构或联合 标识符

结构或联合 :

struct union

结构说明表 :

结构说明

结构说明表 结构说明联合内容定义为 :

结构说明 :

指示符修饰符表 结构说明符表 ;

指示符修饰符表 :

类型指示符 指 示 符 修 饰 符 表 opt

类型修饰符 指 示 符 修 饰 符 表 opt

结构说明符表 :

结构说明符

结构说明符表 ,结构说明符

具 有 union 类 型 的 变 量 存 储 这 个 类 型 定 义 的 值 之 一 。 相 同 的 规 则 控 制 结构 和 联 合 说 明 。 联 合 也 可 以 有 位 域 。

联 合 的 成 员 不 能 有 一 个 不 完 整 的 类 型 、 类 型 void 或 函 数 类 型 。 因 此 成员 不 能 是 该 联 合 的 一 个 实 例 但 可 以 是 说 明 的 联 合 类 型 的 指 针 。

  • 个 联 合 类 型 说 明 只 是 一 个 模 板 ,存 储 器 不 保 存 直 到 说

    明 该 变 量 。

注 意 : 如 果 说 明 一 个 有 两 个 类 型 的 联 合 ,但 该 联 合 用 其 它 类 型 访 问 ,其 结 果是 不 可 靠 的 。 例 如 , 说 明 一 个 float 和 int 的 联 合 , 存 储 一 个 float 值 ,但 以 后作 为 int 访 问 它 的 值 。 在 这 种 情 况 下 , 该 值 依 赖 于 float 值 的 内 部 存 储 。其 整 数 值 是 不 可 靠 的 。

例 子

如 下 是 联 合 的 例 子

union sign/* 一个定义和一个说明 */

{

int svar; unsigned uvar;

} number;

这 个 例 子 用 sign 类 型 定 义 了 一 个 联 合 , 说 明 一 个 命 名 为 number 的 变 量 ,

它 有 两 个 成 员 :

svar 是 一 个 有 符 号 整 数 和 一 个 无 符 号 整 数 uvar。 这 个 说 明 允 许 number 的 当 前 值 作 为 一 个 有 符 号 的 或 无 符 号 的 值 存 储 。 与 这 个 联 合 类 型 关 联 的标 志 是 sign 。

union /* 定义一个名称为 screen 的一个二维数组 */

{

struct

{

unsigned int icon : 8; unsigned color : 4;

} window1; int screenval;

} screen[25][80];

screen 数 组 包 含 2000 个 元 素 , 该 数 组 的 每 个 元 素 是 具 有 两 个 成员 :Window1 和 screenval 的 单 个 联 合 。 w indow1 成 员 是 具 有 两 个 位 域 的成 员 :icon 和 color 的 结 构 。 screenval 成 员 是 一 个 int。 在 任 何 时 候 , 每 个联 合 成 员 保 存 screenval 表 示 的 int 或 w indow1 表 示 的 结 构 。

Microsoft 特 殊 处 →

当 一 个 联 合 是 另 一 个 结 构 或 联 合 的 成 员 时 可 以 无 名 地 说 明 嵌 套 的 联 合 。如 下 是 一 个 无 名 联 合 的 例 子 :

struct str

{

int a,b;

union /* 无名的联合 */

{

char c[4]; long l; float f;

};

char c_array[10];

} my_str;

.

.

.

my_str.l == 0L; /*my_str 联合中一个域的引用 */

联 合 经 常 嵌 套 在 一 个 结 构 中 , 该 结 构 包 括 这 样 的 一 个 域 , 在 任 何 特 定 时 间 , 给 出 包 含 在 该 联 合 中 数 据 的 类 型 。下 面 是 这 样 的 一 个 联 合 的 说 明 的 例 子 : struct x

{

int type_tag; union

{

int x;

float y;

}

}

有 关 引 用 联 合 的 信 息 参 见 第 4 章 “ 表 达 式 和 赋 值 ” 中 的 “ 结 构 和 联 合 成员 ” 。

Microsoft 特 殊 处 结 束

联 合 的 存 储

与 一 个 联 合 变 量 关 联 的 存 储 是 该 联 合 中 最 大 成 员 所 需 要 的 存 储 。 当 存 储较 小 成 员 时 , 该 联 合 变 量 可 以 包 含 未 用 的 存 储 器 空 间 。 所 有 成 员 存 储 在相 同 存 储 器 中 并 起 始 于 相 同 的 地 址 。

每 次 把 一 个 值 赋 给 不 同 成 员 时 ,原 来 存 储 的 值 被 覆 盖 。 例 如 : union /* 定 义 一 个 名 称 为 x 的 联 合 */

{

char *a,b; float f[20];

} x;

x 联 合 的 成 员 根 据 它 们 说 明 的 次 序 依 次 是 一 个 char 值 的 指 针 、 一 个 char 值 和 一 个 float 值 的 数 组 。 x 分 配 的 存 储 是 具 有 20 个 元 素 的 数 组 f 所 需要 的 存 储 ,因 为 f 是 最 长 的 联 合 成 员 。

由 于 该 联 合 没 有 关 联 的 标 志 , 它 的 类 型 是 未 命 名 或 “ 无 名 的 ”。

数 组 说 明

  • 个 “ 数 组 说 明 ” 命 名 数 组 和 指 定 其 元 素 的 类 型 , 它 还 定 义 了 数 组 中 的元 素 个 数 。 具 有 数 组 类 型 的 变 量 是 数 组 元 素 类 型 的 指 针 。

语法说明

说明指示符 初 始 化 说 明 符 表 opt;

初始化说明符表 : 初始化说明符

初始化说明符表 , 初始化说明符初始化说明符 :

说明符

说明符 = 初始化器说明符 :

指针 opt 直接说明符

直接说明符 :

直接说明符 [ 常量表达式 opt ]

因 为 常 量 表 达 式 是 任 选 的 , 其 语 法 有 两 种 格 式 :

  • 第 一 种 格 式 定 义 一 个 数 组 变 量 。 方 括 号 中 的 常 量 表 达 式 参 量 指 出 该数 组 中 的 元 素 个 数 , 该 常 量 表 达 式 如 果 出 现 必 须 具 有 整 数 类 型 , 并 且具 有 一 个 大 于 0 的 值 。 每 个 元 素 具 有 类 型 指 示 符 给 定 的 类 型 。 它 可以 是 非 void 之 外 的 任 何 类 型 。 一 个 数 组 元 素 不 能 是 一 个 函 数 类 型 。

  • 第 二 种 格 式 说 明 一 个 在 其 它 地 方 定 义 的 变 量 。 它 省 略 方 括 号 中 的 常量 表 达 式 , 但 不 是 方 括 号 。 只 有 在 以 前 初 始 化 该 数 组 并 说 明 它 为 一个 参 量 或 在 程 序 中 其 它 地 方 显 式 定 义 的 一 个 数 组 的 引 用 时 才 可 使 用这 种 格 式 。

在 两 种 格 式 中 , 直 接 说 明 符 命 名 该 变 量 并 可 以 修 改 该 变 量 的 类 型 。 直 接说 明 符 后 的 方 括 号 ([]) 修 改 该 说 明 符 为 一 个 数 组 类 型 。

类 型 修 饰 符 可 以 应 用 在 一 个 数 组 类 型 对 象 的 说 明 中 , 但 该 修 饰 符 应 用 于元 素 而 不 是 数 组 本 身 。

你 可 以 在 数 组 说 明 符 之 后 跟 随 一 个 括 起 的 常 量 表 达 式 表 来 说 明 一 个 数 组的 数 组 ( 一 个 “ 多 维 ” 数 组 ), 格 式 为 :

类 型 指 示 符 说 明 符 [ 常 量 表 达 式 ][ 常 量 表 达 式 ]...

括 号 中 的 每 个 常 量 表 达 式 定 义 给 定 维 数 的 元 素 个 数 : 二 维 数 组 有 两 个 括起 的 表 达 式 、 三 维 数 组 有 三 个 括 起 的 表 达 式 等 等 。 如 果 你 已 经 初 始 化 该数 组 , 说 明 它 是 一 个 参 数 或 者 说 明 它 作 为 程 序 中 其 它 地 方 显 式 定 义 的 一个 数 组 的 引 用 , 那 么 你 可 以 省 略 第 一 个 常 量 表 达 式 。

你 可 以 通 过 使 用 复 杂 说 明 符 定 义 各 种 类 型 的 指 针 数 组 ,正 如 本 章 后 面“ 解释 更 复 杂 的 说 明 符 ” 中 描 述 的 。

数 组 以 行 方 式 存 储 , 例如 , 如 下 数 组 由 两 行 组 成 ,每 行 三 列 : char A[2][3];

首 先 存 储 第 一 行 的 三 个 列 , 接 着 是 第 二 行 的 三 个 列 。 这 意 味 着 最 后 一 个

下 标 更 快 速 改 变 。

为 了 引 用 一 个 数 组 的 单 个 元 素 ,使 用 一 个 下 标 表 达 式 ,正 如 第 4 章 “ 表 达

式 和 赋 值 ” 中 的 “ 后 缀 运 算 符 ” 中 描 述 的 。例 子

这 些 例 子 说 明 了 数 组 的 说 明 ;

float matrix[10][15];

该 二 维 数 组 命 名 为 matrix ,有 150 个 元 素 ,每 个 元 素 具 有 float 类 型 。

struct{ float x,y;

}complex[100];

它 是 一 个 结 构 数 组 的 说 明 。 这 个 数 组 有 100 个 元 素 , 每 个 元 素 是 包 含 两个 成 员 的 结 构 。

extern char *name[];

这 个 语 句 说 明 一 个 指 向 char 的 数 组 的 类 型 和 名 称 。 name 的 实 际 定 义 出现 在 其 它 地 方 。

Microsoft 特 殊 处 →

整 数 的 类 型 需 要 保 存 一 个 数 组 的 最 大 尺 寸 是 size_t 的 尺 寸 , 它 定 义 在STDDEF.H 头 文 件 中 。 size_t 是 一 个 unsigned int, 其 范 围 是 0x00000000 到 0x7CFFFFFF 。

Microsoft 特 殊 处 结 束

数 组 的 存 储

与 一 个 数 组 类 型 关 联 的 存 储 是 其 所 有 元 素 需 要 的 存 储 。 一 个 数 组 的 所 有元 素 从 第 一 个 元 素 到 最 后 一 个 元 素 以 相 邻 方 式 存 储 并 逐 步 增 大 存 储 器 位

置 。

指 针 说 明

一个 “ 指 针 说 明 ” 命 名 一 个 指 针 变 量 并 指 定 该 变 量 指 向 的 对 象 的 类 型 。

以 指 针 说 明 的 一 个 变 量 保 存 一 个 存 储 器 地 址 。

语 法 说明符 :

指针 opt 直接说明符直接说明符 :

标识符

(说明符 )

直接说明符 [ 常量表达式 opt ]

直接说明符 ( 参数类型表 ) 直接说明符 ( 标识符表 opt )

指针 :

  • 类型修饰符表 opt

  • 类型修饰符表 opt 指针类型修饰符表 :

类型修饰符

类型修饰符表 类型修饰符

类 型 指 示 符 给 出 该 对 象 的 类 型 , 它 可 以 是 任 何 基 本 的 、 结 构 或 联 合 类 型 。指 针 变 量 也 可 以 指 向 函 数 、 数 组 和 其 它 函 数 ( 有 关 说 明 和 解 释 更 复 杂 指

针 类 型 的 信 息 , 参 见 本 章 后 面 的 “ 解 释 更 复 杂 的 说 明 符 ” )。

通 过 使 类 型 指 示 符 为 void, 你 可 以 推 迟 该 类 型 规 格 到 指 针 所 指 地 方 。 这样 的 一 个 项 作 为 “ void 的 指 针 ” 写 成 void* 。 一 个 说 明 为 void 的 指 针 的变 量 可 以 用 于 任 何 类 型 的 对 象 的 指 针 。 但 为 了 在 指 针 上 或 所 指 对 象 上 执行 更 多 操 作 ,对 于 每 种 操 作 , 所 指 的 类 型 必 须 显 式 指 定 ( 类 型 char * 和 类 型void * 的 变 量 是 赋 值 兼 容 的 , 而 不 使 用 类 型 造 型 )。 这 样 的 转 换 与 一 个 类型 造 型 是 一 致 的 ( 有 关 更 多 信 息 ,参 见 第 4 章 “ 表 达 式 和 赋 值 ” 中 的 “ 类型 造 型 转 换 ” )。

类 型 修 饰 符 可 以 是 const 或 volatile,或 者 两 者 。 它 们 分 别 指 出 该 指 针 不能 被 程 序 本 身 修 改 (const) 或 者 该 指 针 可 以 被 某 个 超 出 程 序 控 制 的 进 程 合理 地 修 改 (volatile)( 有 关 更 多 信 息 参 见 本 章 前 面 的 “ 类 型 修 饰 符 ” )。

说 明 符 命 名 变 量 , 可 以 包 括 一 个 类 型 修 饰 符 。 例 如 , 如 果 说 明 符 表 示 一 个数 组 , 该 指 针 的 类 型 可 以 修 改 为 一 个 数 组 的 指 针 。

你 可 以 在 你 定 义 结 构 、 联 合 或 枚 举 器 类 型 之 前 说 明 一 个 结 构 、 联 合 或 枚举 器 类 型 的 指 针 。 你 可 以 通 过 使 用 如 下 例 子 所 示 的 结 构 或 联 合 标 志 来 说明 指 针 。 这 样 的 说 明 是 允 许 的 , 因 为 编 辑 器 不 需 要 知 道 该 指 针 变 量 分 配的 结 构 或 联 合 的 空 间 的 尺 寸 。

例 子

如 下 例 子 说 明 指 针 的 说 明 :

char *message; /* 说明 message 的指针变量 */

message 指 针 指 向 char 类 型 的 变 量 。

int *pointers[10];/* 说明一个指针数组 */

pointers 数 组 有 10 个 元 素 , 每 个 元 素 是 int 类 型 变 量 的 指 针 。

int (*pointer)[10]; /* 说明有 10 个元素的数组的指针 */

pointer 变 量 指 向 一 个 有 10 个 元 素 的 数 组 ,该 数 组 中 的 每 个 元 素 具 有 int

类 型 。

int const *x; /* 说明一个指针变量 x, 指向一个常量值 */

指 针 x 可 以 修 改 为 指 向 不 同 的 int 值 ,但 它 指 向 的 值 是 不 能 修 改 的 。

const int some_object = 5; int other_object = 37;

int *const y = &fixed_object;

const volatile *const z = &some_object; int *const volatile w = &some_object;

在 这 个 说 明 中 的 变 量 y 说 明 为 一 个 int 值 的 常 量 指 针 。 它 指 向 的 值 可 以修 改 , 但 指 针 本 身 必 须 总 是 指 向 相 同 的 位 置 :fixed_object 的 地 址 。类 似 地 ,z 是 一 个 常 量 指 针 , 但 它 也 说 明 为 一 个 int 的 指 针 ,其 值 不 能 由 程 序 修 改 。 另一 个 指 示 符 volatile 指 出 虽 然 由 z 所 指 的 const int 的 值 不 能 由 程 序 修 改 , 但 可 以 由 与 程 序 并 发 运 行 的 进 程 合 理 地 修 改 。 w 的 说 明 指 出 该 程 序 不 能改 变 所 指 的 值 , 程 序 不 能 修 改 该 指 针 。

struct list *next, *previous; /* 使用 list 的标志 */

这 个 例 子 说 明 两 个 指 针 变 量 next 和 previous ,指 向 结 构 类 型 list。 这 个 说明 可 以 出 现 在 list 结 构 类 型 定 义 之 前 ( 参 见 下 一 个 例 子 ), 只要 list 类 型 定义 与 该 说 明 具 有 同 样 的 可 见 性 。

struct

{

char *token; int count;

struct list *next,

} line;

变 量 line 具 有 list 命 名 的 结 构 类 型 ,list 结 构 类 型 有 三 个 成 员 : 第 一 个 是 char

值 的 指 针 、 第 二 个 是 int 值 、 第 三 个 是 另 一 个 list 结 构 的 指 针 。

struct id

{

unsigned int id_no; struct name *pname;

} record;

变 量 record 具 有 结 构 类 型 id 。 注 意 pname 说 明 为 另 一 个 结 构 类 型 name

的 指 针 , 这 个 说 明 可 以 出 现 在 name 类 型 定 义 之 前 。

地 址 存 储

一 个 地 址 所 需 的 存 储 数 量 和 地 址 的 含 义 取 决 于 编 译 器 的 实 现 。 不 同 类 型的 指 针 不 保 证 具 有 相 同 的 长 度 。 因 此 ,sizeof(char *) 不 必 等 于 sizeof(int

*)。

Microsoft 特 殊 处 →

对 于 Microsoft C 编 译 器 ,sizeof(char *) 等 于 sizeof(int *) 。Microsoft 特 殊 处 结 束

基 指 针

Microsoft 特 殊 处 →

对 于 M icrosoft32 位 C 编 译 器 ,一 个 基 指 针 是 距 离 一 个 32 位 指 针 基 32 位偏 移 量 。 基 地 址 对 于 练 习 控 制 分 配 对 象 的 段 是 有 用 的 , 由 此 减 小 可 执 行文 件 的 长 度 和 提 高 执 行 速 度 。 通 常 地 , 指 出 一 个 基 指 针 的 格 式 为 :

类 型 __ based( 基 ) 说 明 符

基 地 址 的 “ 基 指 针 ” 的 变 化 能 使 一 个 指 针 的 规 格 像 一 个 基 一 样 。 而 基 指针 是 开 始 于 指 针 开 头 的 存 储 器 段 的 一 个 偏 移 量 。 基 于 指 针 地 址 的 指 针 是

32 位 编 译 中 有 效 __based 关 键 字 仅 有 的 格 式 。 在 这 样 的 编 译 中 , 它 们 是 距离 一 个 32 位 基 的 32 位 位 移 。

基 于 指 针 的 指 针 的 一 个 用 途 是 为 了 包 含 指 针 的 持 久 (persistent) 标 识 符 。由 基 于 一 个 指 针 的 指 针 组 成 一 个 链 表 可 以 存 储 到 磁 盘 中 , 然 后 用 保 持 有效 的 指 针 重 新 加 载 到 存 储 器 的 另 一 个 地 方 。

如 下 例 子 给 出 了 一 个 基 本 指 针 的 指 针 。

void *vpBuffer; struct llist_t

{

void __based(vpBuffer) *vpData;

struct llist_t __based(vpBuffer) *llNext;

};

指 针 vpBuffer 被 赋 给 在 程 序 中 某 个 后 面 的 点 分 配 的 存 储 器 的 地 址 。 该

链 表 相 对 于 vpBuffer 的 值 进 行 重 新 定 位 。

Microsoft 特 殊 处 结 束抽 象 说 明 符

一 个 抽 象 说 明 符 (abstract declarator) 是 没 有 一 个 标 识 符 的 说 明 符 , 由 一 个或 多 个 指 针 、 数 组 或 函 数 修 饰 符 组 成 。 指 针 修 饰 符 (*) 总 是 位 于 一 个 说明 符 中 标 识 符 的 前 面 ; 数 组 ([]) 和 函 数 (()) 修 饰 符 紧 跟 标 识 符 。 知 道 这 些 , 你 可 以 确 定 标 识 符 出 现 在 一 个 抽 象 说 明 符 中 的 位 置 并 相 应 地 解 释 该 说 明符 。 有 关 复 杂 说 明 符 的 另 外 信 息 和 例 子 , 参 见 下 一 节 “ 解 释 更 复 杂 的 说明 符 ”。 通 用 的 typedef 可 以 用 来 简 化 说 明 符 , 参 见 本 章 后 面 的 “ typedef 说 明 ”。

抽 象 说 明 符 可 以 是 复 杂 的 , 一 个 复 杂 抽 象 说 明 符 中 的 圆 括 号 指 出 一 个 特定 的 解 释 ,正 如 说 明 中 它 们 为 复 杂 说 明 符 所 做 的 那 样 。

这 些 例 子 说 明 抽 象 说 明 符 :

int * /* 一个 int 类型的指针的类型名称 */ int *[3] /* 三个 int 指针的数组 */

int (*)[5] /* 五个 int 的数组的指针 */

int *() /* 没有参数并返回 int 的指针的函数 */

/* 一个没有参数并返回 int 的指针的函数的指针 */ int (*)(void)

/* 一 个 未 指 定 元 素 个 数 的 数 组 , 其 元 素 是 这 样 的 函 数 的 指 针 , 每 个 函 数 有 一 个

unsigned int

参数和其它未指定个数的参数并返回 int*/ int (*count[]) (unsigned int,...)

注 意 : 抽 象 说 明 符 不 允 许 由 一 个 空 括 号 集 () 组 成 , 因 为 这 是 模 糊 的 。 不 可

能 确 定 该 隐 含 的 标 识 符 是 否 属 于 括 号 内 ( 这 种 情 况 中 它 是 一 个 不 能 修 改的 类 型 ) 或 是 否 在 括 号 之 前 ( 这 种 情 况 下 它 是 一 个 函 数 类 型 ) 。

解 释 更 复 杂 的 说 明 符

你 可 以 在 括 号 中 包 含 任 何 说 明 符 来 指 出 一 个“ 复 杂 说 明 符 ”的 特 殊 解 释 。一 个 复 杂 说 明 符 是 由 多 个 数 组 、 指 针 或 函 数 修 饰 符 修 饰 的 标 识 符 。 你 可以 将 各 种 数 组 、 指 针 和 函 数 修 饰 符 的 组 合 应 用 于 单 个 标 识 符 。 通 常 , typedef 可 以 用 来 简 化 说 明 。 参 见 本 章 后 面 的 “ typedef 说 明 ”。

在 解 释 复 杂 说 明 符 中 , 方 括 号 和 圆 括 号 (也 就 是 该 标 识 符 右 边 的 修 饰 符 ) 比星 号 ( 也 就 是 该 标 识 符 左 边 的 修 饰 符 ) 更 优 先 。 方 括 号 和 圆 括 号 具 有 相 同的 优 先 级 且 从 左 到 右 结 合 。 在 说 明 符 完 全 解 释 后 , 最 后 应 用 类 型 指 示 符 。通 过 使 用 圆 括 号 你 可 以 覆 盖 缺 省 的 结 合 次 序 并 强 制 一 个 特 定 的 解 释 。 但标 识 符 名 称 不 使 用 圆 括 号 , 这 可 能 误 解 释 为 参 数 表 。

解 释 复 杂 说 明 符 的 简 单 方 法 是 使 用 如 下 四 个 步 骤 “ 从 里 向 外 ” 读 :

  1. 从 标 识 符 开 始 ,直 接 查 找 右 边 的 方 括 号 和 圆 括 号 ( 如 果 有 )。

  2. 解 释 这 些 方 括 号 或 圆 括 号 ,然 后 查 找 右 边 的 星 号 。

  3. 如 果 在 任 何 时 候 遇 到 一 个 右 圆 括 号 , 回 到 前 面 对 圆 括

    号 里 的 内 容 应 用规 则 1 和 规 则 2 。

  4. 应 用 类 型 指 示 符 。

char *( *(*var)() )[10];

^

^

^ ^ ^

^ ^

7

6

4 2 1

3

5

在 这 个 例 子 中 , 步 骤 按 顺 序 标 出 , 并 解 释 如 下 :

  1. 标 识 符 var 说 明

  2. 一 个 指 针

  3. 一 个 函 数 返 回

  4. 一 个 指 针

  5. 一 个 有 10 个 元 素 的 数 组

  6. 一 个 指 针

  7. char 值

例 子

以 下 例 子 说 明 其 它 复 杂 的 说 明 以 及 圆 括 号 如 何 影 响 一 个 说 明 的 含 义 的 。

int *var[5];/* 指向 int 值的数组 */

数 组 修 饰 符 比 指 针 修 饰 符 具 有 更 高 的 优 先 级 ,因 此 var 说 明 为 一 个 数 组 。指 针 修 饰 符 应 用 于 该 数 组 元 素 的 类 型 ; 因此 , 该 数 组 元 素 是 int 值 的 指 针 。

int (*var)[5]; /* int 值的数组的指针 */

在 这 个 var 的 说 明 中 , 圆 括 号 给 出 的 指 针 修 饰 符 比 数 组 修 饰 符 的 优 先 级高 ,var 说 明 成 5 个 int 值 的 数 组 的 指 针 。

long *var (long,long); /* 返回 long 指针的函数 */

函 数 修 饰 符 的 优 先 级 也 比 指 针 修 饰 符 的 级 别 高 。 因 此 这 个 var 的 说 明 用来 说 明 var 是 一 个 函 数 ,其 返 回 一 个 long 值 的 指 针 。 该 函 数 说 明 为 两 个long 值 作 为 参 量 。

long(*var)(long,long), /* 返回 long 的函数的指针 */

这 个 例 子 类 似 于 前 面 的 一 个 , 圆 括 号 给 出 的 指 针 修 饰 符 比 函 数 修 饰 符 具有 更 高 的 优 先 级 ,var 被 说 明 为 一 个 返 回 long 值 的 函 数 的 指 针 。 同 样 , 该函 数 有 两 个 long 参 量 。

struct both/* 函数指针的数组 */

{ /* 返回结构 */ int a;

char b;

} (*var[5])(struct both,struct both);

一 个 数 组 的 元 素 不 能 是 函 数 , 但 这 个 说 明 证 明 了 如 何 说 明 函 数 指 针 的 数组 。 在 这 个 例 子 中 ,var 说 明 成 一 个 函 数 的 5 个 指 针 的 数 组 ,该 函 数 返 回 具有 2 个 成 员 的 结 构 。 该 函 数 的 参 量 说 明 成 具 有 相 同 结 构 类 型 both 的 两个 结 构 。 注 意 , 把 *var[5] 括 起 来 的 圆 括 号 是 必 须 的 , 没 有 它 们 , 该 说 明 是非 法 的 , 试 图 说 明 一 个 函 数 的 数 组 , 如 下 :

/* 非 法 的 */

struch both *var[5](struct both,struch both);

如 下 语 句 说 明 一 个 指 针 数 组 :

unsigned int *(*con s t *name[5][10])(void);

name 数 组 有 50 个 元 素 ,以 多 维 数 组 的 形 式 组 织 , 其 元 素 是 一 个 指 针 的 指针 , 它 是 一 个 常 量 , 这 个 常 量 指 针 指 向 一 个 函 数 , 该 函 数 没 有 参 数 并 返 回 一个 无 符 号 类 型 的 指 针 。

下 一 个 例 子 是 一 个 函 数 ,它 返 回 一 个 具 有 3 个 double 值 的 数 组 的 指 针 : double(*var(double(*)[3]))[3];

在 这 个 说 明 中 , 函 数 返 回 一 个 数 组 的 指 针 , 因 为 返 回 数 组 的 函 数 是 非 法

的 。 这 里 var 说 明 成 一 个 函 数 ,该 函 数 返 回 具 有 三 个 double 值 的 数 组 的指 针 。 该 函 数 var 有 一 个 参 量 ,该 参 量 象 返 回 值 ,它 是 具 有 三 个 double 值的 数 组 的 指 针 。 该 参 量 类 型 是 由 抽 象 说 明 符 给 出 的 。

在 参 量 类 型 中 星 号 外 的 圆 括 号 是 需 要 的 , 没 有 它 们 , 该 参 量 类 型 是 三 个double 值 的 指 针 的 数 组 。 有 关 抽 象 说 明 符 的 讨 论 和 例 子 ,参 见 本 章 前 面的 “ 抽 象 说 明 符 ”。

union sign /* 指 针 数 组 的 数 组 */

{ /* 联 合 的 指 针 */ int x;

unsigned y;

} **var[5][5];

本 例 说 明 了 如 何 放 置 圆 括 号 来 改 变 说 明 的 含 义 。 在 这 个 例 子 中 ,var 是 联

合 指 针 的 5 元 素 数 组 的 指 针 的 5 元 素 数 组 。 对 于 如 何 使 用 typedef 避 免复 杂 说 明 的 例 子 , 参 见 “ typedef 说 明 ”。

初 始 化

一 个 “ 初 始 化 器 ” 是 赋 给 说 明 变 量 的 值 的 序 列 。 你 可 以 通 过 在 变 量 说 明中 将 一 个 初 始 化 器 应 用 于 说 明 符 中 来 设 置 一 个 变 量 的 初 值 。 把 值 或 初 始化 器 的 值 赋 给 变 量 。

下 面 几 小 节 描 述 如 何 初 始 化 标 量 、 集 合 和 字 符 串 类 型 的 变 量 。“ 标 量 类型 ” 包 括 所 有 算 术 类 型 加 上 指 针 。“ 集 合 类 型 ” 包 括 数 组 、 结 构 和 联 合 。

初 始 化 标 量 类 型

当 初 始 化 标 量 类 型 时 , 赋 值 表 达 式 的 值 赋 给 该 变 量 。 应 用 赋 值 的 转 换 规则 (有 关 转 换 规 则 的 信 息 ,参 见 第 4 章 “ 类 型 转 换 ” )。

语法说明 :

说明指示符 初 始 化 说 明 符 表 opt;

说明指示符 :

存储类指示符 说明指示符 opt

类型指示符 说明指示符 opt

类型修饰符 说明指示符 opt

初始化说明符表 : 初始化说明符

初始化说明表 ,初始化说明符

初始化说明符 :

说明符

说明符 = 初始化器 /* 对于标量初始化 */

初始化器 :

赋值表达式

你 可 以 初 始 化 任 何 类 型 的 变 量 ,要 遵 守 如 下 规 则 :

  • 在 文 件 范 围 层 说 明 的 变 量 可 以 初 始 化 。 如 果 你 不 显 式 初 始 化 外 部 层的 变 量 , 它 缺 省 地 初 始 化 为 0 。

  • 一 个 常 量 表 达 式 可 以 用 于 初 始 化 任 何 用 static 存 储 类 指 示 符 说 明的 全 局 变 量 , 被 说 明 为 static 的 变 量 在 程 序 执 行 开 始 被 初 始 化 。 如果 你 不 显 式 初 始 化 一 个 全 局 static 变 量 , 它 缺 省 地 初 始 化 为 0, 每 个具 有 指 针 类 型 的 成 员 都 赋 值 一 个 空 指 针 。

  • 用 auto 或 register 存 储 类 指 示 符 说 明 的 变 量 在 每 次 执 行 控 制 传 给说 明 该 变 量 的 块 时 都 进 行 初 始 化 。 如 果 你 在 一 个 auto 或 register 变 量 说 明 中 省 略 一 个 初 始 化 器 , 该 变 量 的 初 始 化 值 是 不 确 定 的 。 对于 自 动 和 寄 存 器 值 , 初 始 化 器 并 不 限 制 是 一 个 常 量 , 它 可 以 是 包 含 以前 定 义 值 的 任 何 表 达 式 , 甚 至 是 函 数 调 用 。

  • 外 部 变 量 说 明 的 初 始 化 值 和 所 有 static 变 量 的 初 始 值 , 不 论 是 外 部还 是 内 部 的 , 都 必 须 是 一 个 常 量 表 达 式 ( 有 关 更 多 信 息 , 参 见 第 4 章中 的 “ 常 量 表 达 式 ” ) 。 由 于 任 何 外 部 说 明 的 或 静 态 变 量 的 地 址 是常 量 , 它 可 以 用 于 初 始 化 一 个 内 部 说 明 的 static 指 针 变 量 。 但 auto 变 量 的 地 址 不 能 用 于 一 个 静 态 初 始 化 器 , 因 为 对 于 该 块 的 每 次 执 行

它 可 能 有 不 同 的 值 。你 可 以 使 用 常 量 或 变 量 初 始 化 auto 和 register 变 量 。

  • 如 果 一 个 标 识 符 的 说 明 有 块 范 围 , 且 该 标 识 符 有 外 部 连 接 , 该 说 明 不能 有 初 始 化 。

例 子

以 下 例 子 说 明 初 始 化 :

int x=10

整 数 变 量 x 初 始 化 为 常 量 表 达 式 10 。

register int *px=0;

指 针 px 初 始 化 为 0 ,产 生 一 个 “ 空 ” 指 针 。

const int c=(3*1024);

这 个 例 子 使 用 一 个 常 量 表 达 式 (3*1024) 初 始 化 c 为 一 个 不 能 修 改 的 常 量值 ,因 为 有 const 关 键 字 。

int *b=&x;

该 语 句 用 另 一 个 变 量 x 的 地 址 初 始 化 指 针 b 。

int *const a=&z;

指 针 a 用 变 量 z 的 地 址 进 行 初 始 化 。 由 于 它 为 const, 因 此 变 量 a 只 能 初始 化 , 不 能 修 改 。 它 总 是 指 向 相 同 的 位 置 。

int GLOBAL;

int function(void)

{

int LOCAL;

static int *lp=&LOCAL;/* 非法初始化 */ static int *gp=&GLOBAL; /* 合法初始化 */ register int *rp=&LOCAL; /* 合法初始化 */

}

全 局 变 量 GLOBAL 在 外 部 层 说 明 , 因 此 它 有 全 局 生 存 期 。 局 部 变 量LOCAL 有 auto 存 储 类 , 仅 在 说 明 它 的 函 数 执 行 期 间 有 地 址 。 因 此 , 试 图用 LOCAL 的 地 址 初 始 化 static 指 针 变 量 lp 是 不 允 许 的 。 static 指 针 变 量gp 可 以 初 始 化 为 GLOBAL 的 地 址 ,因 为 该 地 址 总 是 相 同 的 。 类 似 地 ,*rp 可 以 初 始 化 ,因 为 rp 是 一 个 局 部 变 量 , 具 有 非 常 量 的 初 始 化 器 ,每 次 进 入 该块 ,LOCAL 有 新 地 址 ,然 后 把 它 赋 给 rp 。

一 初 始 化 集 合 类 型

个 “ 集 合 ” 类 型 是 一 个 结 构 、 联 合 或 数 组 类 型 。 如 果 一 个 集 合 类 型 包 含集 合 类 型 的 成 员 , 可 以 递 归 应 用 初 始 化 规 则 。

语法

初始化器 :

{ 初始化器表 } /* 对于集合初始化 */

{ 初始化器表 ,}

初始化器表 :

初始化器

初始化器表 ,初始化器

初 始 化 器 表 是 由 逗 号 分 隔 的 初 始 化 器 的 表 , 该 表 中 每 个 初 始 化 器 是 一 个常 量 表 达 式 或 一 个 初 始 化 器 表 。 因 此 , 初 始 化 器 是 嵌 套 的 。 这 个 格 式 对于 初 始 化 一 个 集 合 类 型 的 集 合 成 员 时 很 有 用 , 正 如 下 一 小 节 的 例 子 说 明的 。 但 如 果 一 个 自 动 标 识 符 的 初 始 化 器 是 单 个 表 达 式 , 它 不 需 要 是 一 个常 量 表 达 式 ,对 于 标 识 符 的 赋 值 只 不 过 需 要 相 应 的 类 型 。

对 于 每 个 初 始 化 器 表 , 常 量 表 达 式 的 值 依 次 赋 给 该 集 合 变 量 的 对 应 成员 。

如 果 初 始 化 器 表 的 值 比 一 个 集 合 类 型 的 少 , 对 于 外 部 和 静 态 变 量 , 该 集 合类 型 的 余 下 成 员 初 始 化 为 0 。 一 个 自 动 标 识 符 不 显 式 初 始 化 ,则 其 初 始 值是 不 确 定 的 。 如 果 初 始 化 器 表 的 值 比 一 个 集 合 类 型 的 多 , 则 产 生 一 个 错误 。 这 些 规 则 应 用 于 每 个 嵌 入 的 初 始 化 器 表 ,以 及 整 个 集 合 。

一 个 结 构 的 初 始 化 器 是 一 个 相 同 类 型 的 表 达 式 或 包 含 在 花 括 号 ({}) 中 的成 员 的 初 始 化 器 的 表 。 无 名 的 位 域 成 员 不 进 行 初 始 化 。

当 初 始 化 一 个 联 合 时 , 初 始 化 器 表 必 须 是 单 个 常 量 表 达 式 。 该 常 量 表 达式 的 值 赋 给 联 合 的 第 一 个 成 员 。

如 果 一 个 数 组 有 未 知 的 尺 寸 , 初 始 化 器 的 成 员 确 定 该 数 组 的 尺 寸 , 其 类 型也 变 成 完 整 的 。 在 C 中 没 有 方 法 指 出 一 个 初 始 化 器 的 重 复 ,或 者 初 始 化一 个 数 组 中 间 的 元 素 而 不 提 供 其 前 面 的 值 。 如 果 你 在 程 序 中 需 要 这 种 操作 , 在 汇 编 语 言 中 编 写 该 例 程 。 注 意 :初 始 化 器 的 成 员 可 以 设 置 数 组 的 尺寸 :

int x[]={0,1,2}

但 如 果 你 指 出 尺 寸 和 给 出 错 误 的 初 始 化 器 个 数 , 编 译 器 会 产 生 一 个 错

误 。

Microsoft 特 殊 处 →

一 个 数 组 的 最 大 尺 寸 由 size_t 定 义 , 它 定 义 在 STDDEF.H 头 文 件 中 。size_t

是 从 0x00000000 到 0x7CFFFFFF 范 围 的 一 个 unsigned int 值 。

Microsoft 特 殊 处 结 束例 子

这 个 例 子 给 出 了 一 个 数 组 的 初 始 化 器 :

int p[4][3]=

{

{1,1,1},

{2,2,2},

{3,3,3,},

{4,4,4,},

};

这 个 语 句 说 明 p 为 一 个 4 × 3 数 组 ,并 初 始 化 它 的 第 一 行 的 元 素 为 1 ,第 二行 的 元 素 为 2 ,如 此 等 等 直 到 第 四 行 。 注 意 第 三 行 和 第 四 行 的 初 始 化 器 表在 最 后 常 量 表 达 式 之 后 包 含 逗 号 。 最 后 的 初 始 化 器 表 ({4,4,4,},) 也 跟 有逗 号 , 这 些 额 外 的 逗 号 是 允 许 的 但 并 不 需 要 。 分 隔 常 量 表 达 式 只 需 要 一个 逗 号 , 分 隔 初 始 化 器 表 也 只 需 要 一 个 逗 号 。

如 果 集 合 成 员 没 有 嵌 入 的 初 始 化 器 , 值 简 单 地 依 次 赋 给 子 集 合 的 每 个 元素 。 因 此 ,前 面 例 子 中 的 初 始 化 与 下 面 的 语 句 是 等 价 的 :

int p[4][3]=

{

1,1,1,2,2,2,3,3,3,4,4,4

};

初 始 化 器 表 中 的 单 个 初 始 化 器 可 以 用 花 括 号 括 起 来 , 这 样 有 助 于 明 确 上述 例 子 。 当 你 初 始 化 一 个 集 合 变 量 时 , 你 必 须 小 心 适 当 地 使 用 花 括 号 和初 始 化 器 表 。 如 下 的 例 子 更 详 细 地 说 明 了 编 译 器 对 花 括 号 的 解 释 。typedef struct

{

int n1,n2,n3;

} triplet;

triplet nlist[2][3] =

{

{{1,2,3},{4,5,6},{7,8,9}}, /* 行 1*/

{{10,11,12},{13,14,15},{16,17,18}} /* 行 2*/

};

在 这 个 例 子 中 ,nlist 说 明 为 2 × 3 结 构 数 组 ,每 个 结 构 有 3 个 成 员 ,该 初 始化 器 的 第 1 行 赋 给 nlist 的 第 一 行 , 如 下 :

  1. 行 1 的 第 一 个 左 花 括 号 指 示 该 编 译 器 开 始 初 始 化 nlist 的 第 一 个 集合 成 员 ( 也 就 是 nlist[0]) 。

  2. 第 二 个 左 花 括 号 指 出 开 始 初 始 化 nlist[0] 的 第 一 个 集 合 成 员 ( 也 就是 nlist[0][0] 处 的 结 构 ) 。

  3. 第 一 个 右 花 括 号 终 止 结 构 nlist[0][0] 的 初 始 化 , 下 一 个 左 花 括 号 开始 nlist[0][1] 的 初 始 化 。

  4. 该 过 程 继 续 直 到 该 行 结 束 , 这 时 封 闭 的 右 花 括 号 终 止 nlist[0] 的 初始 化 。 行 2 以 同 样 的 方 式 把 值 赋 给 nlist 的 第 二 行 。 注 意 , 行 1 和行 2 封 闭 初 始 化 器 的 最 外 面 的 花 括 号 是 需 要 的 。 如 下 例 省 略 了 外 面的 花 括 号 , 构 造 时 产 生 一 个 错 误 :

triplet nlist[2][3]= /* 这引起一个错误 */

{

{1,2,3},{4,5,6},{7,8,9}, /* 行 1*/

{10,11,12},{13,14,15},{16,17,18} /* 行 2*/

};

在 这 个 构 造 中 , 行 1 的 第 一 个 左 花 括 号 开 始 初 始 化 nlist[0], 它 是 三 个 结 构的 一 个 数 组 。

值 1 、 2 和 3 赋 给 第 一 个 结 构 的 三 个 成 员 。 当 遇 到 下 一 个 右 花 括 号 ( 值 3 之 后 的 ) 时 ,完 成 nlist[0]的 初 始 化 ,该 三 结 构 数 组 中 的 两 个 余 下 结 构 自 动 初始 化 为 0 ,类 似 地 ,{4,5,6}初 始 化 nlist 的 第 二 行 中 的 第 一 个 结 构 。 nlist[1] 的 余 下 两 个 结 构 设 置 为 0 。 当 编 译 器 遇 到 下 一 个 初 始 化 器 表 ({7,8,9}), 它试 图 初 始 化 nlist[2]。 由 于 nlist 只 有 两 行 ,这 个 试 图 导 致 一 个 错 误 。

在 下 面 的 例 子 中 , X 的 三 个 int 成 员 分 别 初 始 化 为 1,2 和 3 。

struct list

{

int i,j,k;

float m[2][3];

} x = { 1,

2,

3,

{4.0,4.0,4.0}

};

在 上 述 list 结 构 中 ,m 的 第 一 行 中 的 三 个 元 素 初 始 化 为 4.0;m 的 下 行 的 元素 缺 省 初 始 化 为 0.0 。

union

{

char x[2][3]; int i,j,k;

} y={{

{ ′ 1 ′ },

{ ′ 4 ′ }

}

};

在 这 个 例 子 中 ,联 合 变 量 y 被 初 始 化 。 该 联 合 的 第 一 个 元 素 是 一 个 数 组 , 因 此 , 该 初 始 化 器 是 一 个 集 合 初 始 化 器 。 初 始 化 器 表 { ‘ 1'} 把 值 赋 给 该数 组 的 第 一 行 。由 于 该 表 中 只 有 一 个 值 , 第 一 列 中 的 元 素 初 始 化 为 字 符 1, 该 行 中 余 下 两 个 元 素 缺 省 初 始 化 为 0 。 类 似 地 ,x 的 第 二 行 的 第 一 个 元 素

初 始 化 为 字 符 4 ,该 行 中 余 下 的 两 个 元 素 初 始 化 值 0 。

初 始 化 字 符 串

你 可 以 用 一 个 字 符 串 文 字 ( 或 宽 字 符 串 文 字 ) 初 始 化 一 个 字 符 ( 或 宽 字 符 )

数 组 , 例 如 :

char code[]="abc";

初 始 化 code 为 一 个 4 元 素 的 字 符 数 组 ,第 4 个 元 素 是 空 字 符 , 以 终 止 所 有字 符 串 文 字 。

一 个 标 识 符 表 的 长 度 只 能 等 于 初 始 化 标 识 符 的 个 数 。 如 果 你 指 定 一 个 数组 的 尺 寸 小 于 字 符 串 的 长 度 , 额 外 的 字 符 被 忽 略 。 例 如 , 如 下 说 明 初 始 化code 为 一 个 三 元 素 的 字 符 数 组 :

char code[3]="abcd";

仅 将 初 始 化 器 的 开 头 三 个 字 符 赋 给 code 。 字 符 d 和 该 字 符 串 结 尾 的 空格 字 符 被 丢 弃 。 注 意 将 建 立 一 个 非 终 结 的 字 符 串 ( 也 就 是 ,没 有 一 个 0 值标 志 结 尾 ) 并 产 生 一 个 诊 断 消 息 指 出 这 个 条 件 。

说 明 :

char s[]="abc", t[3]="abc";

等 价 于 :

char s[]={′ a ′ , ′ b ′ , ′ c ′ , ′ \0 ′ }, t[3]={ ′ a ′ , ′ b ′ , ′ c ′ };

如 果 字 符 串 短 于 指 定 的 数 组 尺 寸 ,该 数 组 余 下 的 元 素 初 始 化 为 0 。

Microsoft 特 殊 处 →

在 M icrosoft C 中 ,字 符 串 文 字 的 长 度 可 达 2048 个 字 节 。

Microsoft 特 殊 处 结 束

基 本 类 型 的 存 储

表 3.2 总 结 了 与 每 个 基 本 类 型 关 联 的 存 储 。

表 3.2 基 本 类 型 的 尺 寸

类型 存储

char,unsigned char, signed char

1 字节

short, unsigned short 2 字节

int,unsigned int 4 字节

long,unsigned long 4 字节

float 4 字节

double 8 字节

long double 8 字节

C 数 据 类 型 属 于 通 用 目 录 。“ 整 数 ”类 型 包 括 char 、in t、short 、long 、signed 、unsigned 和 enum 。“ 浮 点 ” 类 型 包 括 float、 double 和 long double 。“ 算术 ” 类 型 包 括 所 有 浮 点 和 整 数 类 型 。

类 型 char

char 类 型 用 于 存 储 可 表 示 字 符 集 的 一 个 成 员 的 整 数 值 。 这 个 整 数 值 是 对

应 指 定 字 符 的 ASCII 码 。

Microsoft 特 殊 处 →

  • 个 unsigned char 的 字 符 值 具 有 从 0 到 0xFF 十 六 进 制 值 的 范 围 。 一 个signed char 具 有 从 0 x 80 到 0x7F 的 范 围 。 这 些 范 围 分 别 转 换 为 0 到 255 十 进 制 和 -128 到 +127 十 进 制 。 编 译 器 选 项 /J 改 变 缺 省 值 从 signed 变 为unsigned 。

Microsoft 特 殊 处 结 束

类 型 int

  • 个 带 符 号 或 无 符 号 int 项 的 尺 寸 是 特 殊 机 器 上 一 个 整 数 的 标 准 尺 寸 , 例如 ,在 16 位 操 作 系 统 中 ,int 类 型 通 常 是 16 位 或 2 个 字 节 。 在 32 位 操 作系 统 中 ,int 类 型 通 常 是 32 位 或 4 个 字 节 。 因 此 ,int 类 型 根 据 目 标 环 境 等价 于 short int 或 long int 类 型 ,unsigned int 类 型 等 价 于 unsigned short 或unsigned long 类 型 。 int 类 型 都 表 示 有 符 号 的 值 ,除 非 有 其 它 指 定 。

类 型 指 定 符 int 和 unsigned int( 或 简 称 unsigned) 定 义 C 语 言 的 某 种 特 征 ( 例如 ,enum 类 型 )。 在 这 些 情 况 下 ,特 殊 实 现 的 int 和 unsigned int 的 定 义 确定 了 实 际 存 储 。

Microsoft 特 殊 处 →

有 符 号 整 数 以 2 的 补 码 格 式 表 示 。 对 于 负 数 , 最 高 位 保 存 符 号 1 ,对 于 正数 和 0 ,它 为 0 。 值 的 范 围 在 表 1.3 中 给 出 , 它 们 来 自 LIMITS.H 头 文 件 。Microsoft 特 殊 处 结 束

注 意 : int 和 unsigned int 类 型 在 C 程 序 中 广 泛 使 用 ,因 为 它 们 允 许 一 个 特

定 机 器 以 其 最 有 效 的 方 式 处 理 整 数 值 。 但 由 于 int 和 unsigned int 类 型 的尺 寸 是 变 化 的 , 依 赖 于 特 定 int 尺 寸 的 程 序 不 能 移 植 到 其 它 机 器 中 。 为 了使 程 序 更 具 移 植 性 , 你 可 以 使 用 一 个 sizeof 运 算 符 的 表 达 式 代 替 硬 码 数据 尺 寸 ( 正 如 第 4 章 “ 表 达 式 和 赋 值 ” 中 “ sizeof 运 算 符 ” 讨 论 的 )。

带 尺 寸 的 整 数 类 型

Microsoft 特 殊 处 →

Microsoft 特 殊 处 支 持 带 尺 寸 的 整 数 类 型 。 你 可 以 使 用 _ _ intn 类 型 指 示 符说 明 8 、16 、32 或 64 位 整 数 变 量 , 这 里 n 是 整 型 变 量 的 尺 寸 , 以 位 为 单 位 。n 的 值 可 以 是 8 、 16 、 32 或 64 。 下 面 的 例 子 说 明 了 四 种 带 尺 寸 的 整 型 :

__ int8 nSmall; // 说明 8 位整数

__ int16 nMedium;// 说明 16 位整数

__ int32 nLarge; // 说明 32 位整数

_ _ int64 nHuge; //说明 64 位整数

开 头 三 个 带 尺 寸 整 型 是 具 有 相 同 尺 寸 的 ANSI 类 型 的 同 义 词 ,这 对 于 编 写

多 平 台 交 叉 移 植 的 代 码 是 有 用 的 。 注 意 __ int8 数 据 类 型 与 char 类 型 是 同义 词 ,

__ int16 与 short 类 型 是 同 义 词 , _

没 有 等 价 的 ANSI 对 应 部 分 。

Microsoft 特 殊 处 结 束

_int32 与 int 类 型 是 同 义 词 。 __ int64 类 型

float 类 型

浮 点 数 使 用 IEEE (电 子 电 气 工 程 师 协 会 ) 格 式 , 单 精 度 浮 点 类 型 有 4 个 字节 ,由 一 个 符 号 位 ,一 个 8 位 超 过 127 二 进 制 指 数 和 一 个 23 位 尾 部 。 尾 部表 示 一 个 1.0 到 2.0 之 间 的 数 。 由 于 尾 数 的 高 端 位 总 是 1 ,它 不 存 储 在 这个 数 中 。 这 种 表 示 给 出 浮 点 类 型 近 似 从 3.4E-38 到 3.4E+38 的 范 围 。

你 根 据 应 用 的 需 要 说 明 一 个 变 量 为 浮 点 数 或 双 精 度 数 。 这 两 种 类 型 之 间的 差 别 是 它 们 能 表 示 、 它 们 需 要 存 储 的 有 效 位 数 和 它 们 的 范 围 。 表 3.3 说 明 了 它 们 在 有 效 位 数 和 存 储 要 求 方 面 的 差 异 。

表 3. 3 浮 点 类 型

类型

有 效 数 字

字节个数

浮点

6-7

4

双精度

15-16

8

浮 点 变 量 用 一 个 尾 部 表 示 , 它 包 含 该 数 值 和 指 数 的 值 , 指 数 包 含 该 数 值 的大 小 次 序 。 表 3.4 说 明 了 每 个 浮 点 类 型 分 配 给 尾 部 和 指 数 的 位 数 。 任 何浮 点 或 双 精 度 数 最 重 要 的 位 总 是 符 号 位 , 如 果 它 为 1, 该 数 值 认 为 是 负 数 ; 否 则 , 该 数 值 认 为 是 正 数 。

表 3.4 指 数 和 尾 部 的 长 度

类型

指 数 长 度

尾部长度

浮点

8 位

23 位

双精度

11 位

52 位

因 为 指 数 以 无 符 号 格 式 存 储 , 指 数 用 它 的 可 能 值 的 一 半 进 行 偏 置 。 对 于浮 点 类 型 ,该 偏 置 为 127; 对 于 双 精 度 类 型 , 该 偏 置 为 1023 。 你 可 以 通 过 从指 数 值 中 减 去 偏 置 值 来 计 算 实 际 的 指 数 值 。

尾 数 以 大 于 或 等 于 1 且 小 于 2 的 二 进 制 分 数 进 行 存 储 。 对 于 浮 点 和 双 精度 类 型 , 在 尾 数 中 最 重 要 的 位 置 中 隐 含 一 个 引 导 的 1 ,因 此 ,尾 部 实 际 上 分别 是 24 和 53 位 长 , 即 使 该 最 重 要 的 位 没 有 存 储 在 存 储 器 中 。

代 替 上 面 描 述 的 存 储 方 法 , 浮 点 软 件 包 以 反 向 规 格 化 的 数 值 存 储 二 进 制浮 点 数 值 ,“ 反 向 规 格 化 的 数 值 ” 是 具 有 保 留 指 数 值 的 非 0 浮 点 数 值 , 尾数 最 重 要 的 位 总 是 0 。 使 用 反 向 规 格 化 格 式 ,一 个 浮 点 数 值 的 范 围 可 以 在精 度 上 进 行 扩 充 。 你 不 能 控 制 一 个 浮 点 数 是 以 规 格 化 的 格 式 还 是 反 向 规格 化 的 格 式 表 示 。 浮 点 软 件 包 不 使 用 反 向 规 格 化 的 格 式 , 除 非 指 数 小 于规 格 化 的 格 式 中 能 表 示 的 最 小 值 。

表 3.5 给 出 了 每 种 浮 点 类 型 的 变 量 中 能 存 储 的 最 小 值 和 最 大 值 。 这 个 表

中 列 出 的 值 仅 应 用 于 规 格 化 的 浮 点 数 值 。 反 向 规 格 化 的 浮 点 数 值 具 有 一个 更 小 的 最 小 值 。 注 意 80 x 87 寄 存 器 中 保 留 的 数 值 总 是 以 80 位 规 格 化的 格 式 表 示 的 。 仅 当 存 储 32 位 或 64 位 浮 点 变 量 (float 类 型 和 long 类 型的 变 量 ) 时 数 值 可 以 以 反 向 规 格 化 的 格 式 进 行 表 示 。

表 3.5 浮 点 类 型 的 范 围

类型

最小值

最 大 值

浮点

1.175494351E-38

3.402823466E+38

双精度

2.2250738585072014E-308

1.7976931348623158E+308

如 果 精 度 不 是 很 重 要 的 , 考 虑 为 浮 点 变 量 使 用 浮 点 类 型 ; 相 反 如 果 精 度 是最 重 要 的 标 准 , 使 用 双 精 度 类 型 。

浮 点 变 量 可 以 提 升 为 一 种 更 大 有 效 位 数 的 类 型 ( 从 浮 点 类 型 到 双 精 度 类型 ) 。 当 你 在 浮 点 变 量 上 执 行 算 术 运 算 时 这 种 提 升 经 常 出 现 。 算 术 运 算总 是 取 最 高 精 度 作 为 变 量 的 高 精 度 。

例 如 , 考 虑 如 下 类 型 说 明 :

float f_short; double f_long;

long double f_longer;

f_short=f_short*f_long;

在 上 述 例 子 中 , 变 量 f_short 提 升 为 双 精 度 类 型 , 且 由 f_long 相 乘 。 那 么 结果 在 赋 给 f_short 之 前 舍 入 为 浮 点 类 型 。

在 下 面 例 子 中 ( 使 用 前 面 例 子 中 的 说 明 ), 算 术 运 算 在 变 量 的 浮 点 (32 位 ) 精度 上 进 行 的 。 然 后 把 结 果 提 升 为 双 精 度 类 型 :

f_longer=f_short*f_short;

double 类 型

具 有 double 类 型 的 双 精 度 值 有 8 个 字 节 。 该 格 式 类 似 于 float 格 式 , 除 了它 有 11 位 超 过 1023 指 数 和 一 个 52 位 尾 数 加 上 隐 含 的 高 端 1 位 外 。 该格 式 给 出 double 类 型 的 近 似 范 围 是 从 1.7E-308 到 1.7E+308 。

Microsoft 特 殊 处 →

double 类 型 包 含 64 位 :1 个 符 号 位 ,11 个 指 数 位 和 52 个 尾 数 位 。 它 的 范围 是 +/-1.7E308, 至 少 有 15 个 数 字 的 精 度 。

Microsoft 特 殊 处 结 束

long double 类 型

一 个 变 量 的 值 的 范 围 由 给 定 位 数 内 部 表 示 的 最 小 值 和 最 大 值 定 界 。 但 因为 C 的 约 定 规 则 ( 在 第 4 章 “ 表 达 式 和 赋 值 ” 中 的 “ 类 型 转 换 ” 中 详 细讨 论 ), 你 不 能 在 表 达 式 中 为 一 个 特 定 类 型 的 常 量 总 是 使 用 最 大 值 或 最 小值 。

例 如 , 常 量 表 达 式 -32768 由 算 术 负 运 算 符 (-) 应 用 于 常 量 32768 组 成 的 ,由于 32768 太 大 不 能 作 为 一 个 short int 数 表 示 , 它 被 给 以 long 类 型 。 结 果 , 常 量 表 达 式 -32768 为 long 类 型 。

你 只 能 通 过 类 型 造 型 强 制 为 short 类 型 来 以 short int 表 示 -32768 。 在 类型 造 型 中 没 有 信 息 丢 弃 ,因 为 -32768 可 以 以 2 字 节 进 行 内 部 表 示 。 在 十进 制 表 示 中 , 值 65000 作 为 一 个 有 符 号 的 常 量 ,它 给 以 long 类 型 , 因 为65000 不 适 合 于 short 。这 样 的 65000 值 只 能 通 过 类 型 造 型 强 制 为 unsigned short 类 型 或 给 定 该 值 以 八 进 制 或 十 六 进 制 表 示 , 或 者 指 定 它 为 65000U 来 作 为 unsigned short 类 型 表 示 。你 可 以 造 型 强 制 这 个 值 为 unsigned short 类 型 而 不 丢 失 信 息 ,因 为 作 为 一 个 无 符 号 数 值 ,65000 适 合 于 以 2 个 字 节表 示 。

Microsoft 特 殊 处 →

long double 包 含 80 个 位 :1 位 表 示 符 号 ,15 位 表 示 指 数 ,64 位 表 示 尾 数 。

它 的 范 围 是 +/-1.2E4932 ,其 精 度 至 少 为 19 个 数 字 。 虽 然 long double 和double 是 分 开 的 类 型 , 但 long double 和 double 的 表 示 是 一 致 的 。Microsoft 特 殊 处 结 束

不 完 整 类 型

  • 个 不 完 整 类 型 是 描 述 一 个 标 识 符 而 缺 乏 确 定 该 标 识 符 尺 寸 所 需 信 息 的类 型 。 一 个 “ 不 完 整 类 型 ” 可 以 是 :
  • 一 个 没 有 指 出 其 成 员 的 结 构 类 型 。

  • 一 个 没 有 指 出 其 成 员 的 联 合 类 型 。

  • 一 个 没 有 指 出 维 数 的 数 组 类 型 。

void 类 型 是 一 个 不 能 完 成 的 不 完 整 类 型 。 为 了 完 成 一 个 不 完 整 类 型 , 指出 缺 少 的 信 息 , 如 下 例 子 说 明 如 何 建 立 和 完 成 不 完 整 的 类 型 。

  • 为 了 建 立 一 个 不 完 整 结 构 类 型 , 说 明 一 个 结 构 类 型 不 指 出 它 的 成员 。 在 如 下 例 子 中 ,PS 指 针 指 向 一 个 称 为 student 的 不 完 整 结 构 类型 :

struct student *ps;

  • 为 了 完 成 一 个 不 完 整 结 构 类 型 , 在 后 面 同 一 范 围 内 用 其 指 定 的 成 员说 明 相 同 的 结 构 类 型 :

struct student

{

int unm;

} /*student 结构现在完整了 */

  • 为 了 建 立 一 个 不 完 整 的 数 组 类 型 , 说 明 一 个 数 组 类 型 而 不 指 定 它 的重 复 计 数 , 例 如 :

char a[]; /*a 有不完整类型 */

  • 为 了 完 成 一 个 不 完 整 的 数 组 类 型 , 在 后 面 同 一 范 围 内 用 指 定 的 重 复计 数 说 明 相 同 的 名 称 :

char a[25]; /*a 现在有一个完整的类型 */

typedef 说 明

  • 个 typedef 说 明 是 一 个 用 typedef 作 为 存 储 类 的 说 明 。 该 说 明 符 变 成 一个 新 类 型 。 你 可 以 使 用 typedef 说 明 为 C 已 经 定 义 的 类 型 或 你 已 说 明 过的 类 型 构 造 更 短 或 更 有 意 义 的 名 称 。

typedef 名 称 允 许 你 封 装 可 以 改 变 的 详 细 的 实 现 。

  • 个 typedef 说 明 的 解 释 方 式 与 变 量 或 函 数 说 明 的 解 释 方 式 相 同 ,但 该 标识 符 代 替 该 说 明 指 定 的 假 设 类 型 ,变 成 该 类 型 的 同 义 词 。

语法说明 :

说明指示符 初 始 化 说 明 符 表 opt

说明指示符 :

存储类指示符 说明指示符 opt

类型指示符 说明指示符 opt

类型修饰符 说明指示符 opt

存储类指示符 :

typedef

类型指示符 : void char short int

long float double signed unsigned

结构或联合指示符

枚举指示符

typedef 名称

typedef 名称 :

标识符

注 意 , 一 个 typedef 说 明 不 能 建 立 类 型 , 它 为 现 存 类 型 或 以 其 它 方 式 指 定类 型 的 名 称 建 立 一 个 同 义 词 。 当 一 个 typedef 名 称 用 作 一 个 类 型 指 示 符时 , 它 可 以 用 某 些 类 型 指 示 符 进 行 组 合 , 但 不 能 是 其 它 的 。 可 接 受 的 修 饰符 包 括 const 和 volatile 。

typedef 名 称 与 普 通 标 识 符 共 享 名 称 空 间 ( 有 关 更 多 信 息 ,参 见 第 2 章 “ 程序 结 构 ” 中 的 “ 名 称 空 间 ” ), 因 此 , 一 个 程 序 可 以 有 一 个 typedef 名 称 和相 同 名 称 的 局 部 范 围 标 识 符 。 例 如 :

typedef char FlagType;

int main()

{

}

int myproc(int)

{

int FlagType;

}

当 说 明 一 个 与 typedef 相 同 名 称 的 局 部 范 围 标 识 符 时 ,或 当 在 同 一 范 围 或更 内 层 范 围 中 说 明 一 个 结 构 或 联 合 的 成 员 时 , 必 须 指 出 类 型 指 示 符 。 如下 例 子 说 明 了 这 种 约 束 :

typedef char FlagType; const FlagType x;

为 了 为 一 个 标 识 符 , 一 个 结 构 成 员 或 者 一 个 联 合 成 员 重 新 使 用 FlagType

名 称 , 必 须 提 供 其 类 型 :

const int FlagType; /* 需要类型指示符 */

如 下 这 样 是 不 足 够 的 :

const FlagType; /* 不完整规格 */

因 为 FlagType 作 为 该 类 型 的 一 部 分 , 不 是 一 个 重 新 说 明 的 标 识 符 。 如 下说 明 是 一 个 非 法 的 说 明 :

int ; /* 非法说明 */

你 可 以 用 typedef 说 明 任 何 类 型 ,包 括 指 针 、 函 数 和 数 组 类 型 。 你 可 以 在定 义 一 个 结 构 或 联 合 类 型 之 前 说 明 该 结 构 或 联 合 类 型 的 指 针 的 typedef 名 称 , 以 及 该 定 义 与 该 说 明 具 有 相 同 的 可 见 性 。

typedef 名 称 可 以 用 于 提 高 代 码 的 可 读 性 。 所 有 如 下 的 三 个 signal 说 明都 精 确 指 出 相 同 类 型 ,开 头 一 个 没 有 使 用 任 何 typedef 名 称 :

typedef void fv(int),(*pfv)(int); /*typedef 说 明 */

void (*signal(int,void(*)(int)))(int);

fv *signal(int,fv*); /* 使用 typedef 类型 */ pfv signal(int,pfv); /* 使用 typedef 类型 */ 例 子

下 面 的 例 子 说 明 了 typedef 说 明 :

typedef int WHOLE; /* 说明 WHOLE 为 int 的同义词 */

注 意 WHOLE 现 在 可 以 用 在 变 量 说 明 中 ,例 如 WHOLE i; 或 const WHOLE i;但 说 明 long WHOLE i; 是 非 法 的 。

typedef struct club

{

char name[30];

int size,year;

}GROUP;

这 个 语 句 说 明 GROUP 是 一 个 具 有 三 个 成 员 的 结 构 类 型 。 因 为 也 指 定 了一 个 结 构 标 志 club,typedef 名称 (GROUP) 或 结 构 标 志 可 以 用 在 说 明 中 ,你必 须 用 标 志 使 用 结 构 关 键 字 , 不 能 用 typedef 名 称 使 用 结 构 关 键 字 。typedef GROUP *PG; /* 使 用 前 面 typedef 名 称 说 明 一 个 指 针 */

类 型 PG 说 明 为 GROUP 类 型 的 一 个 指 针 ,它 又 被 定 义 为 一 个 结 构 类 型 。

typedef void DRAWF(int,int );

这 个 例 子 提 供 DRAWF 类 型 , 它 作 为 一 个 函 数 , 没 有 返 回 值 ,有 两 个 int 参量 。 例 如 ,说 明 :

DRAWF box;

等 价 于 说 明 :

void box(int,int);

扩 充 的 存 储 类 属 性

Microsoft 特 殊 处 →

扩 充 的 属 性 语 法 简 化 和 标 准 化 C 语 言 的 M icrosoft 特 殊 处 扩 充 。 使 用 扩充 的 属 性 的 存 储 类 属 性 包 括 thread 、 naked 、 dllimport 和 dllexport 。

特 定 存 储 类 信 息 的 扩 充 属 性 语 法 使 用 __declspec 关 键 字 , 它 指 出 一 个 给 定类 型 的 实 例 , 采 用 M icrosoft 特 殊 存 储 类 属 性 (thread 、 naked 、 dllimport 或 dllexport) 进 行 存 储 。 其 它 存 储 类 修 饰 符 的 例 子 包 括 static 和 extern 关

键 字 , 但 这 些 关 键 字 是 ANSI C 部 分 ,因 此 不 能 被 扩 充 属 性 语 法 覆 盖 。

语法

存储类指示符 :

__ declspec( 扩充的说明修饰符序列 )/*Microsoft 特殊处 */

扩充的说明修饰符序列 : 扩充的说明修饰符 opt

扩充的说明修饰符序列 扩充的说明修饰符

扩充的说明修饰符 : thread

naked dllimport dllexport

用 空 白 分 隔 说 明 修 饰 符 。 注 意 扩 充 的 说 明 修 饰 符 序 列 可 以 为 空 , 在 这 种

情 况 下 , __ declspec 没 有 作 用 。

thread 、 naked 、 dllimport 和 dllexport 存 储 类 属 性 仅 是 它 们 应 用 的 数 据 或函 数 的 说 明 的 特 性 (property); 它 们 不 能 重 新 定 义 函 数 本 身 的 类 型 属 性 。thread 属 性 只 影 响 数 据 。 naked 属 性 只 影 响 函 数 。 dllimport 和 dllexport 属 性 影 响 函 数 和 数 据 。

Microsoft 特 处 殊 结 束

DLL 输 入 和 输 出

Microsoft 特 殊 处 →

Naked

dllimport 和 dllexport 存 储 类 修 饰 符 是 C 语 言 的 M icrosoft 特 殊 处 扩 充 。这 些 修 饰 符 定 义 DLL 的 客 户 界 面 ( 可 扩 充 文 件 或 另 外 的 DLL )。 有 关 使用 这 些 修 饰 符 的 特 殊 信 息 , 参 见 第 6 章 “ 函 数 ” 中 的 “ DLL 输 入 和 输 出函 数 ”。

Microsoft 特 殊 处 结 束

Microsoft 特 殊 处 →

naked 存 储 类 属 性 是 C 语 言 的 M icrosoft 特 殊 处 扩 充 。 编 译 器 为 用 naked 存 储 类 属 性 说 明 的 函 数 生 成 没 有 序 言 和 结 尾 部 分 的 代 码 。 当 你 需 要 使 用内 联 函 数 代 码 编 写 自 己 的 序 言 /结 尾 部 分 代 码 序 列 时 naked 函 数 很 有 用 。naked 函 数 对 于 编 写 虚 拟 设 备 驱 动 程 序 是 有 用 的 。

有 关 使 用 naked 函 数 的 特 定 信 息 , 参 见 第 6 章“ 函 数 ”中 的“ naked 函 数 ”。

Microsoft 特 殊 处 结 束

thread 局 部 存 储

Microsoft 特 殊 处 →

thread 局 部 存 储 (TLS ) 是 在 一 个 给 定 的 多 线 程 进 程 中 每 个 线 程 分 配 特 定线 程 数 据 的 机 制 。 在 标 准 多 线 程 程 序 中 , 数 据 在 一 个 给 定 进 程 的 所 有 线程 中 共 享 , 而 线 程 局 部 存 储 是 分 配 每 个 线 程 数 据 的 机 制 。 有 关 线 程 完 整的 讨 论 , 参 见 联 机 “ 平 台 SDK ” 文 档 中 的 “ 进 程 和 线 程 ”。

Microsoft C 语 言 包 括 扩 充 的 存 储 类 属 性 ,thread 与 __ declspec 关 键 字 一 起使 用 说 明 一 个 线 程 局 部 变 量 。 例 如 , 如 下 代 码 说 明 一 个 整 数 线 程 局 部 变量 并 用 一 个 值 对 其 初 始 化 :

_ _declspec(thread)int tls_i=1;

当 你 说 明 静 态 约 束 线 程 局 部 变 量 时 必 须 遵 守 这 些 指 南 :

  • _ _declspec(thread) 的 使 用 可 以 与 DDL 输 入 的 延 迟 加 载 进 行 交 互 。

  • 你 只 能 把 thread 属 性 应 用 于 数 据 说 明 和 定 义 。 它 不 能 用 于 函 数 说明 或 定 义 。

例 如 , 如 下 代 码 产 生 一 个 编 译 器 错 误 :

#define thread __ declspec(thread) thread void func(); /* 错误 */

  • 你 只 能 在 具 有 静 态 存 储 期 的 数 据 项 上 指 定 thread 属 性 。 这 包 括 全局 数 据 (static 和 extern) 和 局 部 静 态 数 据 。 不 能 用 thread 属 性 说明 自 动 数 据 。 例 如 , 如 下 代 码 产 生 编 译 器 错 误 ;

#define thread __ declspec(thread) void funcl()

{

thread int tls_i; /* 错误 */

}

int func2(thread int tls_i); /* 错误 */

{

return tls_i;

}

  • 你 必 须 为 线 程 局 部 数 据 的 说 明 和 定 义 使 用 thread 属性 , 而 无 论 该 说明 和 定 义 是 出 现 在 相 同 文 件 或 分 开 文 件 中 , 例 如 , 如 下 代 码 产 生 一 个错 误 :

#define thread __ declspec(thread)

extern int tls_i; /* 这产生一个错误 , 因为 */ int thread tls_i; /* 说明和定义不相同 */

  • 你 不 能 使 用 thread 属 性 作 为 一 个 类 型 修 饰 符 。 例 如 , 如 下 代 码 产 生

一 个 编 译 器 错 误 :

char *ch_ _declspec(thread);/* 错误 */

  • 一 个 线 程 局 部 变 量 的 地 址 不 能 作 为 常 量 , 涉 及 到 该 地 址 的 任 何 表 达式 不 能 作 为 一 个 常 量 表 达 式 。 这 意 味 着 你 不 能 使 用 一 个 线 程 局 部 变量 的 地 址 作 为 一 个 指 针 的 初 始 化 器 。 例 如 , 编 译 器 标 志 的 如 下 代 码有 一 个 错 误 :

#define thread __ declspec(thread) thread int tls_i;

int *p=&tls_i; /* 错误 */

  • C 允 许 用 涉 及 自 身 引 用 的 表 达 式 初 始 化 一 个 变 量 , 但 仅 对 非 静 态 范 围的 对 象 , 例 如 :

#define thread __ declspec(thread)

thread int tls_i=tls_i; /* 错误 */

int j=j; /* 错误 */

thread int tls_i=sizeof(tls_i) /* 正确 */

注 意 一 个 初 始 化 变 量 的 sizeof 表 达 式 不 构 成 对 自 身 的 引 用 , 因 而 是 允 许的 。

  • __ declspec(thread) 的 使 用 可 以 与 DLL 输 入 的 延 迟 交 互 。

有 关 使 用 线 程 属 性 的 更 多 信 息 ,参 见 联 机 “ M icrosoft Visual C++6.0 程 序

员 指 南 ” 中 的 “ 多 线 程 主 题 ”。

Microsoft 特 殊 处 结 束