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.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_alistva_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);

FILENAMELINENUMBERWARNING 宏的定义可能包含在与 errmsg() 的声明相同的头文件中。

errmsg() 的调用的样例为:

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