第 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 。
-
应 用 类 型 指 示 符 。
char *( *(*var)() )[10];
^ |
^ |
^ ^ ^ |
^ ^ |
|
---|---|---|---|---|
7 |
6 |
4 2 1 |
3 |
5 |
在 这 个 例 子 中 , 步 骤 按 顺 序 标 出 , 并 解 释 如 下 :
-
标 识 符 var 说 明
-
一 个 指 针
-
一 个 函 数 返 回
-
一 个 指 针
-
一 个 有 10 个 元 素 的 数 组
-
一 个 指 针
-
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 的 第 一 个 左 花 括 号 指 示 该 编 译 器 开 始 初 始 化 nlist 的 第 一 个 集合 成 员 ( 也 就 是 nlist[0]) 。
-
第 二 个 左 花 括 号 指 出 开 始 初 始 化 nlist[0] 的 第 一 个 集 合 成 员 ( 也 就是 nlist[0][0] 处 的 结 构 ) 。
-
第 一 个 右 花 括 号 终 止 结 构 nlist[0][0] 的 初 始 化 , 下 一 个 左 花 括 号 开始 nlist[0][1] 的 初 始 化 。
-
该 过 程 继 续 直 到 该 行 结 束 , 这 时 封 闭 的 右 花 括 号 终 止 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 特 殊 处 结 束