第五章 字符串字面量---一个特殊的数组

字符串字面量(string literal)是一段双引号括起来的多字节字符序列,C/C++将其实现为具有静态存储连续性的字符数组。初学者(包括不少书籍)常将其称为字符串常量,但这说法只在C++成立,C中不成立。C中的常量只包括下列四种:

6.4.4 Constants

 

Syntax

 constant:

integer-constant

floating-constant

enumeration-constant

character-constant

分别是整数常量、浮点常量、枚举常量和字符常量,并不包括字符串字面量。但由于字符串字面量具有静态存储连续性数组类型,并且在表达式中它会根据数组到指针的隐式转换规则转换为一个代表数组首地址(应改为数组首元素地址,2011年4月)的右值指针,因此C中的字符串字面量的首地址及各元素的地址都是地址常量表达式,但字符串字面量本身不是常量,也不是常量表达式。

而C++的情形有所不同,C++将字符串字面量归入了常量当中:

2.13 Literals

 

There are several kinds of literals.21)

 

literal:

integer-literal

character-literal

floating-literal

string-literal

boolean-literal

21) The term “literal” generally designates, in this International Standard, those tokens that are called “constants” in ISO C.

因此C++中的字符串字面量才可称为字符串常量,而且首地址及各元素地址跟C一样,都是地址常量表达式。

字符串字面量在C中具有数组类型char[N],在C++中则为const char[N],在表达式中当发生数组到指针的转换时,对应的等效指针类型分别是char*和const char*,因此,在C中,char *p = “ABCDEF”是合法的,但让人惊奇的是,上述语句在C++中也是合法的!看起来一个pointer to const char指针被赋予了pointer to char指针,似乎违反了C++中指针转换的more cv-qualified原则。其实字符串字面量在C++中存在两种转换,一种转换依据当前上下文环境,另一种遵循数组到指针的转换,C++标准的内容:

2.13.4 String literals

 

……..An ordinary string literal has type “array of const char” and static storage duration (3.7), where is the size of the string as defined below, and is initialized with the given characters.

4.2 Array-to-pointer conversion

 

    A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to char”; a wide string literal can be converted to an rvalue of type “pointer to wchar_t”. In either case, the result is a pointer to the first element of the array. This conversion is considered only when there is an explicit appropriate pointer target type, and not when there is a general need to convert from an lvalue to an rvalue. [Note: this conversion is deprecated. See Annex D. ] For the purpose of ranking in overload resolution (13.3.3.1.1), this conversion is considered an array-to-pointer conversion followed by a qualification conversion (4.4). [Example: "abc" is converted to “pointer to const char” as an array-to-pointer conversion,

and then to “pointer to char” as a qualification conversion. ]

 

在具有显而易见的合适指针目标类型的情况下,例如上述char *p = “ABCDEF”,字符串字面量被转换为char*而不是const char*类型的指针,这个转换实际上是对旧有代码的兼容,是一个特例,而且被指定为deprecated的,将在未来的版本中予以废弃,有些编译器会产生一条提示这是废弃转换的警告。而在函数重载解析中,字符串字面量遵循数组到指针的转换,同时后跟一个限定修饰的转换。

 

虽然字符串字面量在C中类型为char[N],在C++中类型为const char[N],但并不说明C中的字符串字面量可以修改,C++的不可以。字符串字面量是否可以修改与实现数组的类型无关,C之所以没有规定为const char[N],还是出于对旧代码的兼容,而C++规定为const char[N]的原因之一是比C更严格的类型安全。无论C与C++都规定对字符串字面量的修改是未定义的,编译器可以自行处理,也的确存在一些允许修改字符串字面量的编译器,例如老一代的编译器TC,编译器不管是否允许修改字符串字面量,都没有违反标准。

 

对于那些允许修改字符串字面量的编译器,必须考虑这样一个问题,当代码在不同的上下文中引用了同一个字符串字面量时,如果其中一处修改了该字面量,就会影响其它地方的引用。解决方法是允许同一个字面量的多个实例,这样不同上下文之间不会互相干扰,标准把这个问题的决定权留给了编译器:

 

6.4.5 String literals

 

It is unspecified whether these arrays are distinct provided their elements have the appropriate values.

 

在C中,由于字符串字面量不是常量,而且const限定的变量不是常量表达式(C中的常量表达式必须是编译期的),因此所有的常量和常量表达式都是右值。但C++将字符串字面量归入常量,将const限定的变量归入常量表达式,这意味着在C++中存在左值常量和左值常量表达式。

 

C与C++在这方面的差异反映出两者对待常量的不同视角。C认为常量是不应该拥有存储空间的,这是非常传统的观点;而C++把常量的概念延伸到了对象模型,是对对象概念的有益扩展,但同时也带来了一些问题,一个具有对象性质的实体,难以避免存在某些合法或不合法的手段去修改其内容,这种行为常常令常量对象的常量性质处于尴尬的境地,由此也催生了常量折叠这一类巧妙的折中。

原文地址:https://www.cnblogs.com/ywsoftware/p/4518910.html