C字符串保证是数组吗?

4
C字符串(与std :: string 相反)是否保证实现为数组?例如,我有 char const * str =“abc”; 归结起来,问题在于 str + 4 在不解引用的情况下是否为合法指针值。我之所以问这个问题,是因为我不知道C字符串是否由于空字符而成为特例。

“str + 4” 可以保证是一个合法的指针值,但不能保证其可被解引用。 - ildjarn
因为C++中存在C字符串... - Thomas Eding
@ildjarn如果您超出了内存空间,比如这个字符串被存储在进程内存的末尾,它仍然是一个有效的指针吗? - twain249
@twain249:是的,C和C++都保证C数组和C字符串始终具有合法的一过界值。 - ildjarn
4个回答

5

问题的第一部分

C字符串是否保证实现为数组?

例如,我有:char const * str = "abc"

是的,字符串对象是一个数组类型。字符串是一种数据格式,(字符)字符串对象是char类型的array

在您的示例中,str指向字符串字面量"abc"。字符字符串字面量的类型为char[N+1],其中N是字符串的长度(即不包括终止的空字符的字符数)。

以下是标准和K&R第二版的一些参考资料:

C将字符串字面量定义为:

(C99, 6.4.5p2) "A character string literal is a sequence of zero or more multibyte characters enclosed in double-quotes, as in "xyz"."

并且说(重点在于):

C99, 6.4.5p5) "For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence;"

K&R第二版说:

"技术上讲,一个字符串常量是一个字符数组"

"当类似于"hello\n"的字符串常量出现在C程序中时,它被存储为一个包含字符串中字符并以'\0'结尾的字符数组."

问题的第二部分

归根结底,问题是str + 4是否是合法的指针值(不涉及解引用)。

是的,这是一个有效的指针。在您的情况下,str + 4是一个指向数组最后一个元素之后的指针。

有效指针是一个空指针或指向有效对象的指针。对于数组对象的元素,指向该数组对象最后一个元素之后的指针也是有效的指针。

请注意,对于最后一条规则("超过元素的那个"),对于不是数组元素的对象的指针,C将该对象视为具有其元素类型的一个元素长度的数组。

(C99, 6.5.6p7) "对于这些运算符,指向不是数组元素的对象的指针与指向长度为1且类型为该对象类型的数组的第一个元素的指针行为相同。"


实际上,由于字符串字面量的数组特性,&"string" 的类型为 char (*)[7](指向字符数组 7 的指针)。很多编译器在过去会犯这个错误。不确定现在是否还有一些编译器会出现这种情况... - torek
@torek,我使用C标准(C99,7.1.1p1)中定义的“指向字符串的指针”这个术语,即“指向字符串的指针是指向其初始(最低地址)字符的指针”,即使当然一个指向char数组N的指针的类型是char(*)[N]。 - ouah
是的,“指向字符串”的说法是描述在没有前导&地址运算符的情况下编写字符串文字时所得到的内容的好方法。我只是指出字符串非常“数组式”,因此您可以像这样获取它们的地址,就好像您已经执行了:const char String [7] =“string”。 (另外,值得注意的是,尽管“string”的结果类型中缺少const,但该文字本身至少在原则上是只读的。这种在C类型系统中相当糟糕的故障是由于历史原因造成的。) - torek
@torek 顺便说一句,如果我可以在这里说的话,感谢您在clc中发布的所有帖子。对于我们许多人来说,您的帖子是巨大的灵感和知识来源。 - ouah
1
+1,但我希望你在最后仍然使用“合法指针”这个术语,而不是转而使用“有效指针”,因为在C99的6.5.3.2:4和附注87中,“有效指针”或多或少被定义为“可解引用”。 - Pascal Cuoq
1
@PascalCuoq,实际上我使用“有效指针”的称呼,就像《Rationale (C99)》文档(顺便提一下,《H&S参考书》也是这样)中所说的那样。以下是《Rationale》中的内容:“标准中隐含了无效指针的概念。在讨论指针时,标准通常会提到“指向对象的指针”、“指向函数的指针”或“空指针”。地址算术中的一个特殊情况允许指向数组结束后的位置。任何其他指针都是无效的。” - ouah

3

它们保证是一个连续的char序列。如果这是你对数组的定义,那么是的。

在你的例子中,你将会有4个字符,每个字符都有一个空终止符。 str+4 将超出范围。


1
我在打“contiguous”时遇到了困难,出现了红色波浪线。你比我更快地回答了问题,谢谢你,但另一方面,我学会了如何拼写“contiguous” :) - Tobias
1
@Tobias,当我第一次看到这个词时,我以为它是“continuous”的拼写错误。但那是很久以前的事了。 - Mark Ransom

2
C字符串是否保证实现为数组?
在广义的定义下,是的,它们是一系列连续的字符,其中包含一个终止的空字符。
归根结底,问题是str + 4是否合法的指针值
字面量("abc")是存储在进程内存中的数组。类型是const char[4] (在C++中,我不确定在C中是否是char[4])。然后,str是指向字符串字面量第一个元素的指针,表达式str+3是正确的,可以被解引用,指向的字符将为0。表达式str+4是超出数组末尾的指针,不能被解引用。

@MarkRansom:是的,我有一个偏移量错误,我已经纠正了。我假设你指的是原始答案。 - David Rodríguez - dribeas
在C语言中,char[4]确实存在(不包括const)。 - ouah

0
短答案是:是的,它们是。但是,str+4不一定是一个合法的指针,因为1个字符可能不等于1个字节。

嘿,没问题。信息已经更正,不需要降低评分。 :) - Almo
@Tobias sizeof(char) 保证为1。(字节不一定是8位,但char始终为一个字节)。 - asaelr
哦,不知道呢 :) 但是对于7位字节(现在很少见,但它们曾经存在),当char的长度必须至少为8位时,这是如何工作的? - Tobias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接