JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris Studio 12.3:C 用户指南     Oracle Solaris Studio 12.3 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  C 编译器介绍

2.  特定于 C 编译器实现的信息

3.  并行化 C 代码

4.  lint 源代码检验器

5.  基于类型的别名分析

6.  转换为 ISO C

6.1 基本模式

6.1.1 -Xc

6.1.2 -Xa

6.1.3 -Xt

6.1.4 -Xs

6.2 新式函数原型

6.2.1 编写新代码

6.2.2 更新现有代码

6.2.3 混合使用的注意事项

6.3 带有可变参数的函数

6.4 提升:无符号保留与值保留

6.4.1 一些历史背景

6.4.2 编译行为

6.4.3 示例:强制类型转换的使用

6.4.4 示例:相同的结果,不发出警告

6.4.5 整型常量

6.4.6 示例:整形常量

6.5 标记化和预处理

6.5.1 ISO C 转换阶段

6.5.2 旧 C 转换阶段

6.5.3 逻辑源代码行

6.5.4 宏替换

6.5.5 使用字符串

6.5.6 标记粘贴

6.6 constvolatile

6.6.1 仅适用于 lvalue 的类型

6.6.2 派生类型中的类型限定符

6.6.3 const 意味着 readonly

6.6.4 const 用法示例

6.6.5 volatile 用法示例

6.7 多字节字符和宽字符

6.7.1 亚洲语言需要多字节字符

6.7.2 编码变化 (Encoding Variations)

6.7.3 宽字符

6.7.4 C 语言特征

6.8 标准头文件和保留名称

6.8.1 标准头文件

6.8.2 保留供实现使用的名称

6.8.3 保留供扩展使用的名称

6.8.4 可安全使用的名称

6.9 国际化

6.9.1 语言环境

6.9.2 setlocale() 函数

6.9.3 更改的函数

6.9.4 新函数

6.10 表达式中的分组和求值

6.10.1 表达式定义

6.10.2 K&R C 重新整理许可证

6.10.3 ISO C 规则

6.10.4 括号用法

6.10.5 As If 规则

6.11 不完全类型

6.11.1 类型

6.11.2 完成不完全类型

6.11.3 声明

6.11.4 表达式

6.11.5 使用原因

6.11.6 示例:不完全类型

6.12 兼容类型和复合类型

6.12.1 多个声明

6.12.2 分别编译兼容性

6.12.3 单编译兼容性

6.12.4 兼容指针类型

6.12.5 兼容数组类型

6.12.6 兼容函数类型

6.12.7 特殊情况

6.12.8 复合类型

7.  转换应用程序以适用于 64 位环境

8.  cscope:交互检查 C 程序

A.  按功能分组的编译器选项

B.  C 编译器选项参考

C.  实现定义的 ISO/IEC C99 行为

D.  C99 的功能

E.  实现定义的 ISO/IEC C90 行为

F.  ISO C 数据表示法

G.  性能调节

H.  Oracle Solaris Studio C:K&R C 与 ISO C 之间的差异

索引

6.4 提升:无符号保留与值保留

1990 ISO C 标准的补充材料 "Rationale" 部分出现以下信息:"QUIET CHANGE"。依赖于无符号保留算术转换的程序表现各异,可能没有错误消息。此更改被认为是委员会对当前的普遍实践做出的最重大更改。

本节研究此更改如何影响代码。

6.4.1 一些历史背景

在《The C Programming Language》的第一版中,unsigned 准确地指定一种类型,没有 unsigned charunsigned shortunsigned long。但在此后不久,大多数 C 编译器增加了这些类型。有些编译器未实现 unsigned long,但是包含了其他两种类型。自然地,当这些新类型与在表达式中其他类型混合时,实现为类型提升选择不同的规则。

在大多数 C 编译器中,使用更简单的规则,即无符号保留。需要展宽无符号类型时,其将展宽为无符号类型;当将无符号类型与有符号类型混合时,结果是有符号类型。

ISO C 指定的另一个规则称为“值保留”,其中结果类型取决于操作数类型的相对大小。当展宽 unsigned charunsigned short 类型时,如果 int 的长度足以表示较短类型的所有值,则结果类型为 int。否则,结果类型为 unsigned int。对于大多数表达式,值保留规则产生较少意外的算术结果。

6.4.2 编译行为

仅在转换或 ISO 模式下(-Xt -Xs ),ISO C 编译器才会使用无符号的保留提升。在其他两种模式下(符合 (–Xc) 和 ISO (–Xa)),将使用值保留提升规则。

6.4.3 示例:强制类型转换的使用

在以下代码中,假定 unsigned charint 窄。

int f(void)
{
    int i = -2;
    unsigned char uc = 1;

   return (i + uc) < 17;
}

该代码导致编译器在您使用 -xtransition 选项时发出以下警告:

line 6: warning: semantics of "<" change in ISO C; use explicit cast

加法运算结果的类型为 int(值保留)或 unsigned int(无符号保留),但二者之间的位模式不会更改。在二进制补码机器上:

    i:       111...110 (-2)
+   uc:      000...001 ( 1)
===================
        111...111 (-1 or UINT_MAX)

这种位表示对应于 -1(对于 int)或 UINT_MAX(对于 unsigned int)。因此,如果结果的类型为 int,将使用有符号比较,并且小于测试为 true。如果结果的类型为 unsigned int,将使用无符号比较,并且小于测试为 false。

强制类型转换的加法用来指定这两种行为之中所期望的行为:

value preserving:
    (i + (int)uc) < 17
unsigned preserving:
    (i + (unsigned int)uc) < 17

由于不同的编译器对相同的代码选择不同的含义,因此该表达式存在歧义。强制类型转换的加法帮助阅读器并消除警告消息。

相同的位字段值的提升存在同样的情况。在 ISO C 中,如果 intunsigned int 位字段中的位数小于 int 中的位数,则所提升的类型为 int;否则,所提升的类型为 unsigned int。在大多数较旧的 C 编译器中,对于显式无符号位字段,所提升的类型为 unsigned int,在其他情况下为 int

强制类型转换的类似使用可以消除存在歧义的情况。

6.4.4 示例:相同的结果,不发出警告

在以下代码中,假定 unsigned shortunsigned char 均比 int 短。

int f(void)
{
    unsigned short us;
    unsigned char uc;
    return uc < us;
}

在此示例中,两个自动变量会同时提升为 intunsigned int,因此比较有时无符号,有时带符号。然而,由于两种选择的结果相同,因此 C 编译器并不向您发出警告。

6.4.5 整型常量

与表达式一样,有些整型常量的类型规则已更改。在 K&R C 中,无后缀二进制常量仅在其值足以表示 int 时才具有类型 int。无后缀八进制或十六进制常量仅在其值足以表示 unsigned int 时才具有类型 int。否则,整型常量的类型为 long。有时,值用结果类型不足以表示。在 1990 ISO/IEC C 标准中,常量类型是以下列表中与值对应的第一个类型:

当您使用 -xtransition 选项时,对于其行为可能会根据所涉及常量的类型处理规则而更改的任何表达式,ISO C 编译器会向您发出警告。旧整形常量类型处理规则仅在转换模式下使用。ISO 和符合模式使用新规则。


注 - 无后缀十进制常量的类型处理规则已按照 1999 ISO C 标准更改。请参见2.1.1 整型常量


6.4.6 示例:整形常量

在以下代码中,假定 int 为 16 位。

int f(void)
{
    int i = 0;

    return i > 0xffff;
}

由于十六进制常量的类型为 int(在二进制补码机器上,值为 –1)或 unsigned int(值为 65535),因此在 –Xs-Xt 模式下比较为真,在 –Xa–Xc 模式下比较为假。

同样,相应的强制类型转换澄清代码并禁止警告:

-Xt, -Xs modes:
    i > (int)0xffff

-Xa, -Xc modes:
    i > (unsigned int)0xffff
       or
    i > 0xffffU

U 后缀字符是 ISO C 的新增功能,对于较旧的编译器它可能会产生错误消息。