`
java-mans
  • 浏览: 11415310 次
文章分类
社区版块
存档分类
最新评论

深入探索 C/C++ 数组与指针的奥秘之五:字符串字面量---一个特殊的数组

 
阅读更多

深入探索 C/C++ 数组与指针的奥秘之五:字符串字面量---一个特殊的数组

字符串字面量(string literal)是一段双引号括起来的多字节字符序列,C/C++ 将其实现为具有静态存储连续性的字符数组。初学者(包括不少书籍)常将其称为字符串常量,但这说法只在 C++ 成立,C 中不成立。C 中的常量只包括下列四种:
6.4.4 Constants
Syntax
constant:
integer-constant
floating-constant
enumeration-constant
character-constant
分别是整数常量、浮点常量、枚举常量和字符常量,并不包括字符串字面量。但由于字符串字面量具有静态存储连续性数组类型,并且在表达式中它会根据数组到指针的隐式转换规则转换为一个代表数组首地址的右值指针,因此 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 n const char” and static storage duration (3.7), where n 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++ 把常量的概念延伸到了对象模型,是对对象概念的有益扩展,但同时也带来了一些问题,一个具有对象性质的实体,难以避免存在某些合法或不合法的手段去修改其内容,这种行为常常令常量对象的常量性质处于尴尬的境地,由此也催生了常量折叠这一类巧妙的折中。
原文链接:http://blog.csdn.net/supermegaboy/archive/2009/11/23/4854987.aspx

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics