Sun Studio 12:C 用户指南

附录 H K&R Sun C 与 Sun ISO C 之间的差异

本附录描述以前的 K&R Sun C 与 Sun ISO C 之间的差异。

有关更多信息,请参见1.2 标准一致性

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__

 

H.2 关键字

下面几个表列出 ISO C 标准、Sun ISO C 编译器以及 Sun C 编译器的关键字。

第一个表列出 ISO C 标准定义的关键字。

表 H–2 ISO C 标准关键字

_Bool1

_Complex1

_Imaginary1

auto

break

case

char

const

continue

default

do

double

else

enum

extern

float

for

goto

if

inline1

int

long

register

restrict

return

short

signed

sizeof

static

struct

switch

typedef

union

unsigned

void

volatile

while

 

 

 

C 编译器还定义一个附加关键字 asm。但是,在 -Xc 模式下不支持 asm。

下面列出 Sun C 中的关键字。

表 H–3 Sun C (K&R) 关键字

asm

auto

break

case

char

continue

default

do

double

else

enum

extern

float

for

fortran

goto

if

int

long

register

return

short

sizeof

static

struct

switch

typedef

union

unsigned

void

while