Oracle® Solaris Studio 12.4:C 用户指南

退出打印视图

更新时间: 2014 年 12 月
 
 

Oracle Solaris Studio C:K&R C 与 ISO C 之间的差异

本附录介绍早期 K&R Oracle Solaris Studio C 与 Oracle Solaris Studio ISO C 之间的差异。

有关更多信息,请参见标准符合性

I.1 不兼容性

表 I-1  K&R C 与 ISO C 不兼容的内容
主题
Solaris Studio C (K&R)
Solaris Studio 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 和运算类型使用成员选择运算符 (’.,->’) 处理其他 structsunions 的成员。
要求各个唯一 struct/union 具有自己的唯一名称空间。
作为 lvalue 的强制类型转换
支持将整数类型和指针类型强制转换为 lvalue。例如:
(char *)ip = &char;
不支持此功能。
隐含的 int 声明
支持不带显式类型说明符的声明。num; 等声明被视为隐含的 int。例如:
num; /*num 隐含为 int*/
int num2; /* 显式声明 num2*/
/* declared an 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
此外,预处理程序无法识别该方法。相反,它将两个标记之间的注释视为空白。
预处理程序重新扫描
预处理程序递归替换:
#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 中,因此在编译过程中不会直接调用 cpp(除了在 -Xs 模式中)。
使用反斜杠的行串联
不识别此上下文中的反斜杠字符。
要求换行符紧跟在反斜杠字符后面并拼接在一起。
文本字符串中的三字母
不支持此 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 功能。
预处理程序指令
支持两个 pragma unknown_control_flowmakes_regs_inconsistent 以及 #ident 指令。预处理程序发现无法识别的 pragma 时发出警告。
不指定预处理程序对无法识别的 pragma 的行为。
预定义的宏名称
未定义以下由 ISO C 定义的宏名称:
__STDC__
__DATE__
__TIME__
__LINE__

I.2 关键字

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

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

表 I-2  ISO C 标准关键字
_Alignas2
_Alignof2
_Atomic2
_Bool1
_Complex1
_Generic2
_Imaginary1
_Noreturn2
_Static_assert2
_Thread_local2
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

1 仅使用 -std=c99-std=c11 进行定义

2 仅使用 -std=c11 进行定义

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

下表列出了 K&R Oracle Solaris Studio C 中的关键字。

表 I-3  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