JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris Studio 12.2:C 用户指南
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.4.7 第三个示例:整型常量

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.6.6 volatile 用法示例

6.7 多字节字符和宽字符

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

6.7.2 编码变种

6.7.3 宽字符

6.7.4 转换函数

6.7.5 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.  K&R Solaris Studio C 与 Solaris Studio ISO C 之间的差异

索引

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

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

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

6.4.1 背景

根据 K&R 的《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,则使用带符号比较且小于测试为真;如果结果类型为 unsigned int,则使用无符号比较且小于测试为假。

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

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

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

6.4.4 位字段

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

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

6.4.5 第二个示例:相同的结果

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

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

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

6.4.6 整型常量

与表达式一样,有些整型常量的类型规则已更改。在 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.7 第三个示例:整型常量

在以下代码中,假定 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 的新增功能,对于较旧的编译器它可能会产生错误消息。