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 const 和 volatile

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.3 带有可变参数的函数

在以前的实现中,不能指定函数预期的参数类型,但 ISO C 鼓励您使用原型执行该操作。为支持诸如 printf() 之类的函数,原型语法包括特殊的省略号(…) 终结符。由于一个实现可能需要执行一些特殊操作来处理可变数目的参数,因此 ISO C 要求此类函数的所有声明和定义均包含省略号终结符。

由于参数的 “…” 部分没有名称,因此 stdarg.h 中包含的一组特殊宏为函数提供对这些参数的访问权。此类函数的早期版本必须使用 varargs.h 中包含的类似的宏。

假定要编写的函数是一个称为 errmsg() 的错误处理程序,它返回 void,并且函数的唯一固定参数是指定关于错误消息的详细信息的 int。此参数后跟文件名、行号,或同时跟这二者。这些项后跟格式和参数,与指定错误消息文本的 printf() 类似。

为使此示例可以使用较早的编译器进行编译,要求广泛使用仅针对 ISO C 编译器定义的宏 __STDC__。该函数在相应头文件中的声明为:

#ifdef __STDC__
    void errmsg(int code, ...);
#else
    void errmsg();
#endif

在包含 errmsg() 定义的文件中,新旧风格变得复杂。首先,要包含的头文件取决于编译系统:

#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <stdio.h>

包含 stdio.h 是因为我们稍后调用 fprintf() 和 vfprintf()。

其次是函数的定义。标识符 va_alist 和 va_dcl 是旧式 varargs.h 接口的一部分。

void
#ifdef __STDC__
errmsg(int code, ...)
#else
errmsg(va_alist) va_dcl /* Note: no semicolon! */
#endif
{
   /* more detail below */
}

由于旧式可变参数机制不允许指定任何固定参数,因此必须在可变部分之前访问它们。此外,由于参数的 “…” 部分缺少名称,新的 va_start() 宏具有第二个参数,即 “…” 终结符前面的参数的名称。

作为一种扩展,Oracle Solaris Studio ISO C 允许在没有固定参数的情况下声明和定义函数,如下所示:

int f(...);

对于此类函数,应在第二个参数为空的情况下调用 va_start(),例如:

va_start(ap,)

以下示例是函数的主体:

{
    va_list ap;
    char *fmt;
#ifdef __STDC__
    va_start(ap, code);
#else
    int code;
    va_start(ap);
    /* extract the fixed argument */
    code = va_arg(ap, int);
#endif
    if (code & FILENAME)
        (void)fprintf(stderr, "\"%s\": ", va_arg(ap, char *));
    if (code & LINENUMBER)
        (void)fprintf(stderr, "%d: ", va_arg(ap, int));
    if (code & WARNING)
        (void)fputs("warning: ", stderr);
    fmt = va_arg(ap, char *);
    (void)vfprintf(stderr, fmt, ap);
    va_end(ap);
}

va_arg() 和 va_end() 宏对旧式版本和 ISO C 版本的处理方式相同。由于 va_arg() 更改 ap 的值,因此对 vfprintf() 的调用不能为:

(void)vfprintf(stderr, va_arg(ap, char *), ap);

FILENAME、LINENUMBER 和 WARNING 宏的定义可能包含在与 errmsg() 的声明相同的头文件中。

对 errmsg() 的调用的样例为:

errmsg(FILENAME, "<command line>", "cannot open: %s\n",
argv[optind]);