Sun Studio 12:C 用户指南

H.1 K&R Sun C 与 Sun ISO C 的不兼容性

表 H–1 K&R Sun C 与 Sun ISO C 的不兼容性

主题 

Sun C (K&R) 

Sun ISO C 

main()envp 参数

允许 envp 作为 main() 的第三个参数。

允许第三个参数;但是,该用法并不严格符合 ISO C 标准。 

关键字 

将标识符 constvolatilesigned 视为普通标识符。

constvolatilesigned 是关键字。

块内部的 externstatic 函数声明

将这些函数声明提升为文件作用域。 

ISO 标准不保证块作用域函数声明提升为文件作用域。 

标识符 

允许标识符中使用美元符号 ($)。

不允许使用 $

long float 类型

接受 long float 声明,并将这些声明视为 double

不接受这些声明。 

多字符字符常量 

int mc = ’abcd’;

产生: 

abcd

int mc = ’abcd’;

产生: 

dcba

整型常量 

在八进制换码序列中接受 8 或 9。 

在八进制换码序列中不接受 8 或 9。 

赋值操作符 

将以下操作符对视为两个标记,因此允许它们之间出现空白: 

*=、/=、%=、+=、-=、<<=、>>=、&=、^=、|=

将它们视为单个标记,因此不允许它们之间出现空白。 

表达式的无符号保留语义 

支持无符号保留,即 unsigned char/short 转换为 unsigned int

支持值保留,即 unsigned char/short 转换为 int

单/双精度计算 

将浮点表达式的操作数提升为 double

声明以返回 float 的函数总是将其返回值提升为 double

允许在单精度计算中执行对 float 的操作。

允许这些函数具有 float 返回类型。

struct/union 成员的名称空间

允许使用成员选择操作符('.''->')的 structunion 和算术类型处理其他 structunion 的成员。

要求各个唯一 struct/union 具有自己的唯一名称空间。

作为 lvalue 的强制类型转换

支持作为 lvalue 的强制类型转换。例如:

(char *)ip = &char;

不支持此功能。 

隐含的 int 声明

支持不带显式类型说明符的声明。num; 等声明被视为隐含的 int。例如:

num; /*num 隐含为 int*/

int num2; /* 显式声明 num2*/

/* 声明一个 int */

不支持 num; 声明(不带显式类型说明符 int),生成语法错误。

空声明 

允许空声明,如: 

int;

除标记之外,禁止空声明。 

类型定义中的类型说明符 

允许 typedef 声明中出现 unsignedshortlong 等类型说明符。例如:

typedef short small;

unsigned small x;

不允许类型说明符修改 typedef 声明。

位字段中允许的类型 

允许所有整型的位字段,包括未命名位字段。 

ABI 要求支持未命名位字段及其他整型。 

只支持类型为 intunsigned intsigned int 的位字段。未定义其他类型。

不完全声明中标记的处理 

忽略不完全类型声明。在以下示例中,f1 是指外部 struct

struct x { . . . } s1;

{struct x; struct y {struct x f1; } s2; struct x

{ . . . };}

在符合 ISO 的实现中,不完整的 structunion 类型说明符将隐藏具有相同标记的封闭声明。

struct/union/enum 声明中的不匹配

允许嵌套的 struct/union 声明中标记的 struct/enum/union 类型出现不匹配。在以下示例中,第二个声明被视为 struct

struct x {. . . }s1;

{union x s2;. . .}

将内部声明视为新声明,隐藏外部标记。 

表达式中的标签 

将标签视为 (void *) lvalue

不允许在表达式中使用标签。 

switch 条件类型

通过将 floatdouble 转换为 int,允许使用这两种类型。

对于 switch 条件类型,只对整型(int、char 和枚举类型)求值。

条件包含指令的语法 

预处理程序忽略 #else#endif 指令后面的结尾标记。

禁止这样的构造。 

标记粘贴和 ## 预处理程序操作符

不识别 ## 操作符。通过在粘贴的两个标记之间放置注释来完成标记粘贴:

#define PASTE(A,B) A/*任意注释*/B

## 定义为执行标记粘贴的预处理程序操作符,如以下示例中所示:

#define PASTE(A,B) A##B

而且,Sun ISO C 预处理程序不识别 Sun C 方法。相反,它将两个标记之间的注释视为空白。 

预处理程序重新扫描 

预处理程序递归替换: 

#define F(X) X(arg)

F(F)

产生 

arg(arg)

在重新扫描过程中,如果在替换列表中找到宏,则不替换宏: 

#define F(X)X(arg)F(F)

产生: 

F(arg)

形式参数列表中的 typedef 名称

可以使用 typedef 名称作为函数声明中的形式参数名称。“隐藏”typedef 声明。

禁止使用声明为 typedef 名称的标识符作为形式参数。

特定于实现的聚集初始化 

对括号中部分省略的初始化函数进行分析和处理时,使用自下而上的算法: 

struct{ int a[3]; int b; }\ w[]={{1},2};

产生 

sizeof(w)=16

w[0].a=1,0,0

w[0].b=2

使用自上而下的分析算法。例如: 

struct{int a[3];int b;}\

w[]={{1},2};

产生 

sizeof(w)=32w[0].a=1,0,0w[0].=0w[1].a=2,0,0w[1].b=0

include 文件的注释

允许在 #include 文件中开始的注释由包含第一个文件的文件终止。

在编译的转换阶段中注释被替换为空白字符,然后再处理 #include 指令。

字符常量中的形式参数替换 

在字符常量与替换列表宏匹配时,替换字符常量中的字符: 

#define charize(c)’c’

charize(Z)

产生: 

’Z’

不替换字符: 

#define charize(c) ’c’charize(Z)

产生: 

’c’

字符串常量中的形式参数替换 

字符串常量包含形式参数时,预处理程序替换形式参数: 

#define stringize(str) ’str’

stringize(foo)

产生: 

”foo”

应使用 # 预处理程序操作符:

#define stringize(str) ’str’

stringize(foo)

产生: 

”str”

内置到编译器“前端”的预处理程序 

编译器调用 cpp(1),然后调用编译系统的所有其他组件,具体取决于指定的选项。

ISO C 转换阶段 1-4 涉及预处理程序指令的处理,直接内置到 acomp 中,因此除了在 -Xs 模式下之外,编译时不直接调用 cpp。

使用反斜杠的行并置 

不识别此上下文中的反斜杠字符。 

要求换行符紧跟在反斜杠字符后面并拼接在一起。 

字符串文字中的三字母 

不支持此 ISO C 功能。 

 

asm 关键字

asm 是关键字。

asm 视为普通标识符。

标识符的链接 

不将未初始化的 static 声明视为暂定声明。因此,第二个声明将生成“重新声明”错误,如下所示:

static int i = 1;

static int i;

将未初始化的 static 声明视为暂定声明。

名称空间 

只分为三类:struct/union/enum 标记、struct/union/enum 的成员及其他。

识别四种不同的名称空间:标签名称、标记(跟在关键字 struct、unionenum 后面的名称)、struct/union/enum 的成员以及普通标识符。

long double 类型

不支持。 

允许 long double 类型声明。

浮点常量 

不支持浮点后缀 flFL

 

无后缀整型常量可以具有不同的类型 

不支持整型常量后缀 u 和 U

 

宽字符常量 

不接受宽字符常量的 ISO C 语法,如下所示: 

wchar_t wc = L’x’;

支持此语法。 

'\a''\x'

将它们视为字符 'a' 和 'x'。

'\a''\x' 视为特殊转义序列。

字符串文字的并置 

不支持相邻字符串文字的 ISO C 并置。 

 

宽字符字符串文字语法 

不支持此示例中所示的 ISO C 宽字符字符串文字语法: 

wchar_t *ws = L"hello";

支持此语法。 

指针:void *char *

支持 ISO C void * 功能。

 

一元加运算符 

不支持此 ISO C 功能。 

 

函数原型-省略号 

不支持。 

ISO C 定义使用省略号 "..." 表示变量参数列表。 

类型定义 

禁止另一个具有相同类型名称的声明在内部块中重新声明 typedef

允许另一个具有相同类型名称的声明在内部块中重新声明 typedef

extern 变量的初始化

不支持显式声明为 extern 的变量的初始化。

将显式声明为 extern 的变量的初始化视为定义。

聚集的初始化 

不支持联合或自动结构的 ISO C 初始化。 

 

原型 

不支持此 ISO C 功能。 

 

预处理指令的语法 

仅识别第一列中具有 # 的指令。

ISO C 允许在 # 指令前使用前导空白字符。

# 预处理程序操作符

不支持 ISO C # 预处理程序操作符。 

 

#error 指令

不支持此 ISO C 功能。 

 

预处理程序指令 

支持 unknown_control_flowmakes_regs_inconsistent 两个 pragma 以及 #ident 指令。预处理程序发现无法识别的 pragma 时发出警告。

不指定预处理程序对无法识别的 pragma 的行为。 

预定义宏名称 

未定义以下由 ISO C 定义的宏名称: 

__STDC__

__DATE__

__TIME__

__LINE__