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.10 表达式中的分组和求值

K&R C 为编译器提供一个许可证,以便重新整理包含算术上可交换并且关联的相邻运算符(甚至出现圆括号)的表达式。但是,ISO C 没有给编译器同样的自由。

本节通过考虑以下代码片段中的表达式语句,讨论这两个 C 定义之间的差异,并阐明表达式的副作用、分组以及求值之间的差别。

int i, *p, f(void), g(void);
/*...*/
i = *++p + f() + g();

6.10.1 表达式定义

表达式的副作用是修改内存并访问 volatile 限定对象。示例表达式的副作用是更新 ip 以及函数 f()g() 内包含的任何副作用。

表达式的分组是值与其他值和运算符相结合的一种方式。示例表达式的分组主要是加法的执行顺序。

表达式的求值包括生成结果值所必需的所有运算。要对表达式求值,所有指定的副作用必须在上下两个序列点之间发生,并且使用特定的分组执行指定的操作。对于示例表达式,更新 ip 必须发生在前一语句之后并且通过该表达式语句的 ; 执行。函数调用可以在前一语句之后按任一顺序、任何时间执行,但必须在使用其返回值之前。特别地,在使用操作的值之前,导致内存更新的运算符不需要分配新值。

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

由于加法在算术上可交换并且关联,因此 K&R C 重新整理许可证适用于该示例表达式。为了区别常规圆括号和表达式的实际分组,左、右花括号指定分组。表达式的三种可能的分组为:

i = { {*++p + f()} + g() };
i = { *++p + {f() + g()} };
i = { {*++p + g()} + f() };

给定 K&R C 规则,所有这些分组均有效。此外,即使表达式是按以下任意方式编写的,所有这些分组仍有效:

i = *++p + (f() + g());
i = (g() + *++p) + f();

如果在溢出导致异常的体系结构上对该表达式求值,或者加法和减法在溢出时不是互逆运算,则当一个加法运算溢出时,这三种分组表现不同。

对于这些体系结构上的此类表达式,K&R C 中唯一可用的求助措施是分割表达式以强制进行特定的分组。以下可能的重写分别强制执行以上三种分组:

i = *++p; i += f(); i += g()
i = f(); i += g(); i += *++p;
i = *++p; i += g(); i += f();

6.10.3 ISO C 规则

对于算术上可交换并且关联但实际上在目标体系结构上并非如此的操作,ISO C 不允许进行重新整理。因此,ISO C 语法的优先级和关联性完整描述了所有表达式的分组。所有表达式在进行解析时必须进行分组。所考虑的表达式按以下方式分组:

i = { {*++p + f()} + g() };

此代码仍不表示必须在 g() 之前调用 f(),也不表示必须在调用 g() 之前增大 p

在 ISO C 中,不需要为了避免意外的溢出而分割表达式。

6.10.4 括号用法

由于不完全的理解或不准确的表示,ISO C 经常被错误地描述为支持圆括号或根据圆括号求值。

由于 ISO C 表达式的分组通过自身的解析指定,括号仅充当控制如何解析表达式的一种方法。表达式的自然优先级和关联性具有与括号完全相同的权重。

按如下所示写入的前一表达式可能不会对其分组或求值造成其他影响。

i = (((*(++p)) + f()) + g());

6.10.5 As If 规则

K&R C 重新整理规则的一些原因包括:

ISO C 委员会最终确认:重新整理规则应用于所描述的目标体系结构时,本来是要作为 as if 规则的一个实例。ISO C 的 as if 规则是通用许可证,它允许实现任意偏离抽象机器描述,只要偏离不更改有效 C 程序的行为。

由于无法通知此类重新分组,因此允许在任何机器上重新整理所有二元按位运算符(移位除外)。在溢出回绕的典型二进制补码机器上,可以由于相同原因重新整理涉及乘法或加法的整型表达式。

因此,C 中的此更改对大多数 C 程序员没有重大影响.