第1章 C的基本元素

第1章 C的基本元素

本章描述了C程序语言的组成元素,包括用于构造一个C程序的名称、数组和字符。ANSI C语法称这些组成元素为“语言符号”,本章解释如何定义语言符号以及编译器如何对它们求值的。

包括如下主题:

*语言符号

*注释

*关键词

*标识符

*常量

*字符串文字

*标点和特定字符

本章还包括三字母、浮点常量、整数常量和转义序列的参考表。“运算符”是指定值如何操作的符号(有单字符和字符组合),每个符号都解释为单个单元,称为一个语言符号。有关详细信息参见第4章“表达式和赋值”。


语言符号

在C源程序中,编译器识别的基本元素是“语言符号”,一个语言符号是编译器不能分成组成成分元素的源程序文本。

语法语言符号:

关键词

标识符

常量

字符串文字

运算符

标点字符

注意:有关ANSI语言规定的解释,参见本卷后面附录A“C语言语法总结”的引言部分。

在本章中描述的关键词、标识符、常量、字符串文字和运算符都是语言符号的例子。标点字符和中括号([])、花括号({})、圆括号(())和逗号(,)也是语言符号。

空白字符

空格、制表、换行、回车、换页、纵向制表(vertical tab)和换行(newline)字符都称为空白字符(white-space),因为它们具有相同的功能,即作为打印页上单词和行之间的空白,使其更容易阅读。通过空白字符和其它语言符号,例如运算符和标点,从而对语言符号进行定界。当对代码进行词法分析时,C编译器忽略空白字符,除非使用它们作为分隔符或者字符常量或字符串文字的组成成分。使用空白字符使程序更具可读性。注意编译器也把注释作为空白字符处理。


注 释

一个“注释”是以正向斜线/星号的组合(/*)(编译器处理作为单个空白字符,其它忽略)开头的字符序列。一个注释可以包含可表示字符集的字符的任何组合,包括换行字符,但不能有“结束注释”定界符(*/)。注释可以多于一行但不能嵌套。注释可以出现在一个空白字符允许出现的任何地方,由于编译器把一个注释作为一个空白字符处理,你不能在语言符号中包含注释,编译器忽略注释中的字符。

使用注释文档化你的代码,这个例子是编译器接受的一个注释:

/* Comments can contain keywords such as

for and while without generating errors. */

注释可以与一个代码语句出现在同一行:

printf("Hello/n"); /* Comments can go here */

你可以在函数或程序模块之前选择一个描述性的注释块:

/* MATHERR.C illustrates writing an error routine

* for math functions.

*/

既然注释不能包含嵌套的注释,这个例子导致一个错误:

/* Comment out this routine for testing

/* Open file */

fh=_open("myfile.c",_O_RDONLY);

. . .*/

这个错误出现是因为编译器识别第一个*/,单词Open file之后作为注释结束,它处理余下的文本,在发现注释外面的*/时产生一个错误。当你使用注释表示某些代码行为了测试而不激活时,预处理器命令#if和#endif以及条件编译是另一种有用的方法。有关详细信息参见本卷后面“预处理器参考”中的“预处理器命令”。

Microsoft特殊处

Microsoft编译器还支持以两个正向斜线(//)开头的单行注释。如果你用/Za(ANSI标准)编译,这些注释产生错误,另外这些注释不能超过第二行。// This is a valid comment注释以两个正向斜线(//)开头,以下一个换行字符结束,不能在前加上一个转义字符。在下面的例子中,换行符有一个反向斜线(/),建立一个“转义序列”。这个转义序列导致编译器把下一行作为前面行的一部分进行处理(有关详细信息,参见本章后面的“转义序列”)。

// my comment /

i++;

因此,i++;语句被注释了。

Microsoft C缺省是启用Microsoft扩充的。使用/Za关闭这些扩充。

Microsoft特殊处结束

语言符号的求值

当编译器解释语言符号时,它在移到下一个语言符号之前在单个语言符号中包含尽可能多的字符。因为这种行为,编译器不可能在不用空白的字符分隔它们时来解释语言符号,对于如下表达式:

i+++j

在这个例子中,编译器首先从三个加号中产生最长可能的运算符(++),然后处理余下的加号作为一个加法运算符(+)。因此,该表达式解释为(i++)+(j),而不是(i)+(++j)。在这个类似的情况下,使用空白和括号避免模糊性,并确保正确的表达式计算。

Microsoft特殊处

C编译器处理CTRL+Z字符为一个文件结尾指示器,它忽略CTRL+Z之后的任何文本。

Microsoft特殊处结束


关 键 词

关键词是C编译器中具有特定意义的单词。在翻译阶段7和8,一个标识符不能和C关键词具有相同的拼写和大小写(参见本卷后面“预处理器参考”中的转换阶段的描述;有关标识符的信息,参见下一节“标识符”)。C语言使用如下关键词:

auto double int struct

break else long switch

case enum register typedef

char extern return union

const float short unsigned

continue for signed void

default goto sizeof volatile

do if static while

你不能重新定义关键词,但你可以使用C预处理器命令在编译之前指定用于替换关键词的文本。

Microsoft特殊处

ANSI C标准允许用两个下划线引导的标识符作为编译执行的保留字。因此,Microsoft约定Microsoft的指定关键词之前带两个下划线。这些词不能用作标识符名称。对于ANSI命名标识符的描述,包括双下划线的使用,参见下一节“标识符”。

Microsoft C编译器识别的关键词和指定标识符如下:

_asm dllimport2 __int8 naked2_

_based1 __except __int16 __stdcall

__cdecl __fastcall __int32 thread2

__declspec __finally __int64 __try

dllexport2 __inline __leave

1.__based关键词限制用于32位目标编译。

2.这些是与__declspec一起使用时指定的标识符,它们用在其它上下文中没有限制。缺省地Microsoft扩充是允许的,为了确保你的程序是完整可移植的,你在编译时指定/Za选项(ANSI兼容的编译)来关闭Microsoft扩充。当你这样做后,Microsoft特定关键词是禁止的。

当允许Microsoft扩充时,你可以在程序中使用上面所列的关键词。为了与ANSI一致,这些大多数关键词加上了一个双下划线前缀。但有四个例外,即dllexport,dllimport,naked和thread,仅与__declspc一起使用,因此不需要引导的两个下划线。为了向后兼容,也支持余下的关键字的一个下划线引导的版本。

Microsoft特殊处结束


标 识 符

“标识符”或“符号”是你的程序中提供的变量、类型、函数和标号的名称。标识符在拼写和大小写上必须不同于关键词。你不能使用关键词(C或Microsoft)作为标识符,它们为了特定用途而被保留。你可以通过在变量、类型或函数的说明中指定它来建立一个标识符。在以下例子中,result是一个整数变量的标识符,而main和printf是函数的标识符名称:

void main()
{
int result;
if (result!=0) printf("Bad file handle/n");
}

一旦说明,你可以在后面的程序语句中使用该标识符引用关联的值。一种特定类型的标识符,称为语句标号,它可以用在goto语句中(其说明在第3章“说明和类型”中描述。语句标号在第5章“语句”的“goto和标号语句”中描述)。

语法

标识符:

非数字

标识符 非数字

标识符 数字

非数字:如下之一:

_ a b c d e f g h i j k l m n o p q r s t u v w x y z

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

数字:如下之一:

0 1 2 3 4 5 6 7 8 9

一个标识符名称的第一个字符必须是非数字(也就是,第一个字符必须是一个下划线或者一个大写或小写字母)。ANSI允许一个外部标识符的名称中有6个有效字符,在一个内部标识符(一个函数中)的名称中允许有31个字符。外部标识符(以全局范围说明或用存储类extern说明)要服从另外的命名限制,因为这些标识符可以被其它软件例如链接器处理。

Microsoft特殊处

虽然ANSI允许外部标识符名称中有6个有效字符,允许内部标识符(一个函数中)中有31个字符,但Microsoft C编译器允许一个内部或外部标识符名称中有247个字符。如果不关心与ANSI的兼容性,你可以使用/H选项(限制外部名称的长度)修改这个缺省值为一个较小或较大的值。

Microsoft特殊处结束

C编译器把大写和小写字母当作不同的字符。这个特征称为“大小写敏感的”,允许你建立具有相同的拼写但有一个或多个不同的大小写的不同的标识符。例如,下面每个标识符都是唯一的:

add

ADD

Add

aDD

Microsoft特殊处

不要为标识符选择以两个下划线开头或以一个下划线加上一个大写字母开头的名称。ANSI C标准允许以这些字符组合开头的标识符名称保留为编译器使用。文件层范围的标识符也不要以一个下划线加上一个小写字母开头来命名。以这些字符开头的标识符也是保留的。Microsoft约定使用一个下划线和一个大写字母开头的宏名称以及两个下划线开头的Microsoft特定关键字名称。为了避免任何命名冲突,总是选择不以一个或两个下划线开头的名称,或者以一个下划线加上一个大写字母开头的名称。

Microsoft特殊处结束

下面的例子是满足ANSI和Microsoft命名限制的有效标识符:

j

count

temp1

top_of_page

skip12

LastNum

Microsoft特殊处

虽然源文件中的标识符缺省是大小写敏感的,但目标文件中的符号却不是。Microsoft C在一个编译单元中处理标识符为大小写敏感的。Microsoft链接器是大小写敏感的,你必须根据大小写一致性地指定所有标识符。

“源字符集”是可以在源文件中出现的合法字符集。对于Microsoft C,源字符集是标准ASCII字符集。包括ASCII字符的源字符集和执行字符集用作转义序列。有关执行字符集的信息参见本章后面的“字符常量”。

Microsoft特殊处结束

一个标识符具有“范围”,它是指被程序已知的和“连接”的程序范围,该“连接”确定另一个范围内同名称标识符是否是同一个标识符。这些主题在第2章“程序结构”中的“生存期、范围、可见性和连接”中解释。

多字节和宽字符

一个多字节字符是由一个或多个字节序列组成的一个字符。每个字节序列表示扩展字符集中的单个字符。多字节字符用在字符串例如汉字中。宽字符是总为16位宽的多种语言字符代码。字符常量的类型是char,对于宽字符,其类型为wchar_t。既然宽字符总是固定的长度,使用宽字符可以简化使用国际字符集的程序设计。

宽字符串文字L"hello"变成一个类型wchar_t的6个整数的数组:

{L'h,L'e,L'l,L"l",L'o',O}

单代码(Unicode)规格是宽字符的规格。多字节和宽字符之间进行转换的运行库例程包括mbstowcs、mbtowc、wcstombs和wctomb。

三字母

C源程序的源字符集被包含在7位ASCII字符集中,但不是ISO 646-1983Invariant Code Set的子集。三字母(trigraph)序列允许C程序仅使用ISO(国际标准组织) Invariant Code Set编写。三字母是编译器用对应的标点字符替换的三字符序列(以两个问号开头)。你可以在C源文件中使用三字母,该源文件的字符集不能包含某些标点字符的方便图形表示。

表1.1给出了9个三字母序列。所有源文件中出现的第一行的标点字符都被第2列中对应的字符所替换。

表1.1 三字母序列

三字母标点字符
??=#
??([
??//
??)]
??'^
??<{
??!|
??>}
??-~

一个三字母总是作为单个源字符处理,在第一次转换阶段中,在识别字符串文字和字符常量中的转义字符之前进行三字母的转换。仅识别表1.1中列出的9个三字母,所有其它字符序列不作转换。

字符转义序别/?防止类似三字母的字符序列被误解释(有关转义序列的信息,参见本章后面的“转义序列”)。例如,如果你试图用以下printf语句打印字符串What??!:

printf(“What??!/n");

打印的字符串What|,因为??!是一个三字母,它被|字符所替换。正确打印这个字符串的语句如下:

printf(What?/?!/n");

在这个printf语句中,在第二个问号之前加上一个反斜杠转义字符防止??!作为一个三字母的误解释。


常 量

一个“常量”是一个可以在程序中作为值的一个数、字符,或者字符串。使用常量表示不能修改的浮点数、整数、枚举或字符值。

语法

常量:

浮点常量

整数常量

枚举常量

字符常量

常量通过具有一个值和一个类型来描述。浮点数、整数和字符常量在下面三个小节讨论。枚举常量在第3章“说明和类型”的“枚举说明”中描述。

浮点数常量

一个“浮点数常量”是一个表示带符号实数的十进制数。带符号实数的表示包括一个整数部分、一个小数部分和一个指数。使用浮点常量表示不能改变的浮点值。

语法

浮点常量:

分数常量 指数部分opt浮点后缀opt

数字序列 指数部分 浮点后缀opt

分数常量:

数字序列opt.数字序列

数字序列.

指数部分:

e符号opt数字序列

E符号opt数字序列

符号:如下之一

+ -

数字序列:

数字

数字序列 数字

浮点后缀:如下之一

f l F L

你可以省略小数点之前的数字(该值的整数部分),或小数点之后的数字(小数部分),但不能都省略。仅当你包括一个指数时才可以省去小数点。常量的数字和字符之间不需要空白字符分隔。

如下例子说明了几种浮点常量和表达式的格式:

15.751.575E1 /*=15.75*/

1575e-2 /*=15.75*/

-2.5e-3 /*=-0.0025*/

25E-4 /*=0.0025*/

浮点常量除非前面加有一个负号(-),否则是一个正数。在这种情况下,负号作为单目算术取反运算符处理。浮点常量具有类型float、double、long或long double。

一个没有f、F、l或L后缀的浮点常量具有类型double。如果有f或F后缀,该常量的类型为float;如果有字母l或L后缀,其类型为long double。例如:

100L /*有类型long double*/

100F /*有类型float*/

100D /*有类型double*/

注意,Microsoft C编译器把long double映射成类型double。有关double、float和long类型的信息参见第3章“说明和类型”中的“基本类型存储”。

你可以省略浮点常量的整数部分,如以下例子所示,数值.75可以采用多种方式表示,包括如下:

.0075e2

0.075e1

.075e1

75e-2

浮点常量的限制

Microsoft特殊处

表1.2中给出了浮点常量值的限制,头文件FLOAT.H包含这些信息。

表1.2 浮点常量的限制

常量含义
FLT_DIGq个数字的数值,有q个十进制6
DBL_DIG数字的浮点数可以舍入成一个15
LDBL_DIG浮点表示,回过来时不丢失精度15
FLT_EPSILON最小正数x,并且x+1.0不等于1.01.192092896e-07F
DBL_EPSILON 2.2204460492503131e-016
LDBL_EPSILON 2.2204460492503131e-016
FLT_GUARD 0
FLT_MANT_DIG在浮点有效数字中以???????
FLT_RADIX???????????????
DBL_MANT_DIG指定基数的数字的数值。该基数为2;53
LDBL_MANT_DIG因此这些值指定位53
FLT_MAX最大可表示的浮点数3.402823466e+38F
DBL_MAX 1.7976931348623158e+308
LDBL_MAX 1.7976931348623158e+308
FLT_MAX_10_EXP最大整数,10的这个数的乘方38
DBL_MAX_10_EXP是一个可表示的浮点数308
LDBL_MAX_10_EXP 308
FLT_MAX_EXP最大整数,FLT_RADIX的这个数的乘方128
DBL_MAX_EXP是一个可表示的浮点数1024
LDBL_MAX_EXP 1024
FLT_MIN最小正数1.175494351-38F
DBL_MIN 2.2250738585072014e-308
LDBL_MIN 2.2250738585072014e-308
FLT_MIN_10_EXP最小负整数,10的这个数的乘方-37
DBL_MIN_10_EXP是一个可表示的浮点数-307
LDBL_MIN_10_EXP -307
FLT_MIN_EXP最小负整数,???????
FLT_RADIX????-125
DBL_MIN_EXP?????的这个数的乘方-1021
LDBL_MIN_EXP是一个可表示的浮点数-1021
FLT_NORMALIZE 0
FLT_RADIX指数表示的基数2
_DBL_RADIX 2
_LDBL_RADIX 2
FLT_ROUNDS浮点加法的舍入1(近)
_DBL_ROUNDS模式1(近)
_LDBL_ROUNDS 1(近)

注意:表1.2中的信息可能在将来有不同的实现。

Microsoft特殊处结束

整数常量一“整数常量”是表示一个整数值的十进制(基数为10)、八进制(基数为8)或十六进制(基数为16)的数。使用整数常量表示不能改变的整数值。

语法

整数常量:

十进制常量 整数后缀opt

八进制常量 整数后缀opt

十六进制常量 整数后缀opt十进制常量:

非0数字 十进制常量 数字 八进制常量:

0

八进制常量 八进制数字

十六进制常量:

0x十六进制数字

0X十六进制数字

十六进制常量

十六进制数字非0数字:如下之一

1 2 3 4 5 6 7 8 9

八进制数字:如下之一

0 1 2 3 4 5 6 7

十六进制数字:如下之一

0 1 2 3 4 5 6 7 8 9

a b c d e f

A B C D E F

整数后缀:

无符号后缀 长整数后缀opt

长整数后缀 无符号后缀opt

无符号后缀:如下之一

u U

长整数后缀:如下之一

l L64位整数后缀:

i64

除非整数常量前面有负号(-),否则是正数。负号被解释为单目算术取反运算符(有关这个运算的信息,参见第4章“表达式和赋值”中的“单目算术运算符”)。

如果一个整数常量以0x或0X字母开头,则它是十六进制的;如果以数字0开头,则为八进制数;否则,它假设为十进制数。

下面两行是等价的:

0x1C /* 十进制数28的十六进制表示 */

034/* 十进制数28的八进制表示 */

一个整数常量的数字之间不能用空白字符分开。以下例子是有效的十进制、八进制和十六进制常量:

/*十进制常量*/

10

132

32179

/*八进制常量*/

012

0204

076663

/*十六进制常量*/

0xa或0xA

0x84

0x7dB3或0x7DB3

整数类型

每个整数常量基于它的值和表示方式被给定一个类型。你可以通过在常量的末尾添加字母l或L来强制任何整数常量为long类型。通过添加u或U来强制它为unsigned类型。小写字母l可能与数字1混淆,应避免这样。几个long整数常量的格式如下:

/*长十进制常量*/

10L

79L

/*长八进制常量*/

012L

0115L

/*长十六进制常量*

/0xaL或0xAL

0X4fL或0x4FL

/*无符号长十进制常量*/

776745UL

778866LU

你赋给一个常量的类型依赖于该常量表示的值。一个常量的值必须在其类型可表示的值的范围内,一个常量的类型确定了当该常量用于一个表达式或应用一个负号(-)时执行的转换。这里列出了整数常量的转换规则:

*没有后缀的十进制常量的类型有int、long int或unsigned long int。在该常量的值可以表示的三种类型中第一种类型作为赋给该常量的类型。

*没有后缀的八进制和十六进制常量赋给的类型根据常量的大小可以是int、 unsigned int、long int或unsigned long int。

*带u或U后缀的常量赋给的类型根据它们的大小可以是unsigned int或unsigned long int。l带l或L后缀的常量赋给的类型根据它们的尺寸可以是long int或unsigned long int。

*带u或U和l或L后缀的常量赋给的类型是unsigned long int。

整数限制

Microsoft特殊处

表1.3列出了整数类型的限制,

这些限制定义在标准头文件LIMITS.H中。

Microsoft C还允许说明可变大小的整数变量,可以是大小为8位、16位或32位的整数类型,有关可变大小整数的信息,参见第3章“说明和类型”中的“可变大小整数类型”。

表1.3 整数常量的限制

常量含义
CHAR_BIT不是一个位域的最小变量中的位数8
SCHAR_MIN类型signed char的变量的最小值-128
SCHAR_MAX类型signed char的变量的最大值127
UCHAR_MAX类型unsigned char的变量的最大值225(0xff)
CHAR_MIN类型char的变量的最小值-128;如果使用/J选项则为0
CHAR_MAX类型char的变量的最大值127;如果使用/J选项则为255
MB_LEN_MAX多字符常量中的最大字节数2
SHRT_MIN类型short的变量的最小值-32768
SHRT_MAX类型short的变量的最大值32767
USHRT_MAX类型unsigned short的变量的最大值65535(0xffff)
INT_MIN类型int的变量的最小值-2147483647-1
INT_MAX类型int的变量的最大值2147483647
UINT_MAX类型unsigned int的变量的最大值4294967295(0xffffffff)
LONG_MIN类型long的变量的最小值-2147483647-1
LONG_MAX类型long的变量的最大值2147483647
ULONG_MAX类型unsigned long的变量的最大值4294967295(0xffffffff)

如果一个值超过了最大整数表示,Microsoft编译器产生一个错误。Microsoft特殊处结束

字符常量

一个“字符常量”是由可表示字符集中单个字符由单引号(′′)括起来构成的。字符常量可用来表示执行字符集中的字符。

语法字符常量:

′c字符序列′

L′c字符序列′

c字符序列:

c字符

c字符序列

c字符c字符

源字符集中除单引号(′)、反向斜杠(/)或换行符之外的任何成员。

转义序列

转义序列:

简单转义序列

八进制转义序列

十六进制转义序列

简单转义序列:如下之一:

/a /b /f /n /r /t /v

/' /" // /?

八进制转义序列:

/八进制数字

/八进制数字 八进制数字

/八进制数字 八进制数字 八进制数字

十六进制转义序列:

/x十六进制数字

十六进制转义序列 十六进制数字

字符类型

一个整数字符常量不以字母L开头并具有int类型。一个包含单个字符的整数字符常量的值是作为一个整数解释的字符的数值。例如,字符a的数值是十进制97和十六进制61。

从语法上看,一个“宽字符常量”是一个带前缀字母L的字符常量。一个宽字符常量有类型wchar_t,一个整数类型定义在STDDEF.H头文件中,例如:

charschar=′x′; /*一个字符常量*/

wchar_t wchar=L′x′;/*一个同样字符的宽字符常量*/

宽字符常量有16位宽,指出扩充的执行字符集的成员。它们允许你采用因太大不能由类型char表示的字母表示字符。有关宽字符的更多信息,参见本章前面的“多字节和宽字符”。

执行字符集

本书经常提到“执行字符集”。执行字符集不必与编写C程序使用的源字符集完全相同,执行字符集包括源字符集中所有字符以及空字符、换行符、回退符、水平制表、垂直制表、回车和转义序列。源字符集和执行字符集在其它实现上可能不同。

转义序列

由一个反向斜杠(/)后跟一个字母或一个数字构成的字符组合称之为“转义序列”。为了表示换行符、单引号或某些其它字符常量,你必须使用转义序列。一个转义序列作为单个字符,因此是一个有效的字符常量。 转义序列一般用于指出动作,如在终端和打印机上的回车和制表移动,它们也用来提供非打印字符和有特定意义的字符,如双引号的文字表示。表1.4列出了ANSI转义序列及其表示。

注意,反向斜杠之后加一个问号(/?)指出一个文字问号,在这种情况中,该字符序列可能误解释为一个三字母,有关更多的信息,参见本章前面的“三字母”。

表1.4 转义序列

转义序列表示
/a响铃(警告)
/b回退
/f换页
/n换行
/r回车
/t水平制表
/v垂直制表
/′单引号
/"双引号
//反向斜杠
/?文字问号
/ooo八进制表示的ASCII字符
/xhhh十六进制表示的ASCII字符

Microsoft特殊处

如果一个字符之前的反向斜杠不出现在表1.4中,编译器处理该无定义的字符为该字符本身,例如,/x作为一个x处理。

Microsoft特殊处结束

转义序列允许你把非图形控制字符传送给一个显示设备,例如,ESC字符(/033)经常用作一个终端或打印机的控制命令的第一个字符。有些转义序列是设备特定的。例如,垂直制表和换页转义序列(/v和/f)不能用于屏幕输出,而它们执行适当的打印机操作。

你可以使用反斜杠(/)作为一个续行符,当一个换行符(等价于按RETURN)后立即跟一个反斜杠(/),编译器便忽略该反斜杠和换行符,把下一行作为前面一行的一部分。这主要用于超过一行的预处理定义,例如:

#define assert(exp) /

((exp) ? (void) 0:_assert(#exp,_ _FILE_ _,_ _LINE_ _))

八进制和十六进制字符规格

序列/ooo表示你可以以一个三数字八进制字符代码指定ASCII字符集中的任何字符,该八进制整数的数值指定期待的字符或宽字符的值。类似地,序列/xhhh允许你以一个十六进制字符代码指定任何一个ASCII字符,例如,你可以以正常的C转义序列(/b)或/010(八进制)码或/x008(十六进制)码给出ASCII回退符。

在一个八进制转义序列中你只能使用0~7数字。八进制转义序列不能长于3个数字并以第一个不是一个八进制数字的字符结束。虽然你不需要使用所有三个数字,但必须至少使用一个,例如,ASCII回退符的八进制表示是/10,字母A的八进制表示是/101,正如ASCII表给出的。

类似地,你必须为十六进制转义序列至少给出一个数字,但可以省略第二个和第三个数字。因此,你可以对回退符指出十六进制转义序列为/x8、/x08或/x008。

八进制或十六进制转义序列的值必须在这样的可表示范围内,对于字符常量是类型unsigned char的可表示值范围;对于宽字符常量是类型wchar_t的可表示值范围。有关宽字符常量的信息参见本章前面的“多字节或宽字符”。

不同于八进制转义常量,一个转义序列中十六进制数字的数值是没有限制的,一个十六进制转义序列以第一个不属于十六进制数字的字符终止。因为十六进制数字包括字字母a到f,小心确保该转义序列在指定的数字终止。为了避免混乱,你可以在一个宏定义中放置八进制或十六进制字符定义:

#define Bell ′/x07′

对于十六进制值,你可以分解该字符串以便清楚地显示正确的值:

"/xabc" /*一个字符*/

"/xab" "c" /*两个字符*/


字符串文字

一个“字符串文字”是来自源字符集中的字符用双引号(“”)括起来的字符序列。字符串文字用于表示以空格字符结尾的字符串的字符序列,对于宽字符串文字,其前必须加上前缀L。

语法字符串文字:

"s字符序列opt"

L"s字符序列opt"

s字符序列:

s字符

s字符序列s字符

s字符:

源字符集中除双引号(")、反向斜杠(/)或换行符之外的任何成员

转义序列

如下例子是一个简单的字符串文字:

char amessage="This is a string literal.";

表1.4中列出的所有转义码都是有效的字符串文字。为了在一个字符串文字中表示一个双括号,使用转义序列/"。单引号(′)没有转义序列也可以表示。反向斜杠(/)在一个字符串中的表示是其后必须跟第二个反向斜杠(//)。当一个反向斜杠出现在一行的末尾时,它总是解释成一个续行符。

字符串文字的类型

字符串文字具有char的类型数组(也就是char[])(宽字符串具有wchar_t的类型数组(也就是wchar_t[]))。这样意味着一个字符串是一个具有类型char元素的数组。该数组中元素成员等于该字符串中字符个数加上1即结尾的空格字符。

字符串文字的存储

一个字符串文字的字符顺序存储在相邻的存储器位置。一个字符串文字中的一个转义序列(例如//或/")都作为单个字符计数。一个空格字符(由/0转义序列表示)自动添加,作为每个字符串文字的结尾标志(这出现在转换阶段7中)。注意编译器不可能在不同的地址存储两个相同字符串。/Gf(删除重复字符串)编译器选项强制编译器把相同字符串拷贝放进可执行文件中。

Microsoft特殊处

字符串具有静态存储期。有关静态存储器的信息,参见第3章说明和类型中的“存储类”。

Microsoft特殊处结束

字符串文字连接

为了构成占用多行的字符串文字,你可以连接两个字符串。为此,键入一个反向斜杠,然后按RETURN键。该反向斜杠导致编译器忽略后面的换行符。例如,字符串文字:

"Long strings can be bro/

ken into two or more pieces."

与以下字符串文字是相同的:

"Long strings can be broken into two or more pieces."

字符串连接可以用于以前采用一个反向斜杠跟一个换行字符来输入多于一行的字符串文字的任何地方。

为了在一个字符串文字中强制换行,在该字符串中要求分断该行的地方插入一个换行转义序列(/n),如下:

"Enter a number between 1 and 100/nOr press return"

因为字符串可以在源代码中的任何列开始,并且长字符串可以继续到下一行的任何列,你可以定位该字符串增加源代码的可读性,无论哪种情况输出的屏幕表示不受影响。例如:

printf("This is the first half of the string,"

this is the second half");

字符串的每部分都包含在双引号中,各部分连接起来作为单个字符串来输出,这种连接在转换阶段指定的编译中根据事件的序列来执行。

"This is the first half of the string,this is the second half"

一个字符串指针,初始化为两个由空白分隔的不同字符串文字,而作为单个字符串进行存储(指针在第3章“说明和类型”中的“指针说明”中讨论)。适当地引用,正如下面的例子,结果与前面的例子是相同的:

char *string="This is the first half of the string,"

"this is the second half";

printf("%s",string);

在转换阶段6中,由任何相邻字符串文字或相邻宽字符串文字序列指定的多字节字符序列都连接成单个多字节字符序列。因此,不要设计这样的程序,允许在执行中修改字符串文字。ANSI C标准指出修改一个字符串的结果是不确定的。

最大字符串长度

Microsoft特殊处

ANSI兼容性需要一个编译器在连接之后的一个字符串文字中至多可接受509个字符,在Microsoft C中允许的一个字符串文字的最大长度接近2048个字节。如果字符串文字由包含在双引号中的各部分组成,预处理器把这些部分连接成单个字符串,对于每个连接的行,还增加一个额外字节到字节总数中。

例如,假设一个字符串由40行组成,每行50个字符(共有2000个字符),另有一个7个字符的行,每行用双引号括起来,这样2007个字节加上结尾空格字符的一个字节,总共2008个字节。在连接时,每行增加一个额外字符到第一行,这样总共有2048个字节。注意,如果用续行符(/)代替双引号,预处理器不会为每行都增加一个额外的字符。

Microsoft特殊处结束


标点和特殊字符

在C字符集中标点和特殊字符有各种用途,从组织程序文本到定义编译器或编译的程序的执行功能。它们不指定执行的操作。有些标点符号也是运算符(参见第4章“表达式和赋值”中的“运算符”)。编译器从上下文确定它们的用途。

语法

标点:如下之一

[ ] ( ) { } * , : = ; ... #

这些字符在C中具有特定含义,它们的作用在本书中描述。#号(#)仅在预处理命令中出现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值