我试图了解指针,数组和字符串文字在C ++中的工作方式。
假设我们有以下代码行:
const char* const letters[] = {"A+","A"};
如果我理解正确,则此声明将字母声明为指向常量字符的常量指针数组。根据我的理解,编译器实际上会将每个字符串文字转换为以null结尾的char数组,而每个字母元素实际上是指向该数组第一个元素的常量指针。
例如,letters[0]
实际上是指向“ A +”的“ A”的指针。但是
std::cout<< letters[0];
实际上输出"A+"
到标准输出。怎么会这样?尤其是因为letters[0]
是常量指针?
我的第二个问题与上面的声明有关:如果字符串文字实际上是const char数组,那么为什么下面的代码行
const char* const letters[] = {{'A','+','\0'},{'A','\0'}};
抛出
error: braces around scalar initializer for type ‘const char* const’
const char* const letters[] = {{'A','+','\0'},{'A','\0'}};
^
谢谢!
答案 0 :(得分:2)
该标准规定,就程序而言,字符串文字应表示为静态存储持续时间的const
个字符数组,并带有结尾的'\0'
终止符。该标准未指定编译器如何实现此效果,只是您的程序可以以这种方式处理字符串文字。
因此,要么防止修改字符串文字(例如,将字符串文字传递给期望char *
的函数,这是可诊断的错误,并且代码将无法编译),或者-如果代码可以在类型系统周围工作以进行修改字符串文字中的任何字符-涉及不确定的行为。
在您的示例中,letters[0]
的类型为const char *
,其值等于字符串文字"A+"
中第一个字符的地址。
std::cout
的 std::ostream
具有接受operator<<()
的{{1}}。该函数由语句const char *
调用,并且该函数假定std::cout << letters[0]
点位于const char *
的零终止数组处。遍历该数组,单独输出每个字符,直到遇到结尾的char
(不输出)。
问题是,'\0'
表示指针指向const char *
,而不是不能更改指针(即const char
)。因此可以增加指针,但不能更改其指向的值。所以,如果我们这样做
char * const
循环遍历字符串文字 const char *p = letters[0];
while (*p != '\0')
{
std::cout << *p;
++p;
}
的字符,分别打印每个字符,并在到达"A+"
时停止(上面产生相同的可观察输出'\0'
)。 / p>
但是,在上面
std::cout << letters[0]
将不会编译,因为*p = 'C';
的定义告诉编译器p
无法更改。但是,仍然允许递增*p
。
原因
p
不编译是因为数组初始化程序无法用于初始化指针。例如;
const char* const letters [] = {{'A','+','\0'},{'A','\0'}};
都是非法的。相反,需要定义一个数组,而不是指针。
const int *nums = {1,2,3}; // invalid
const * const int nums2 [] = {{1,2,3}, {4,5,6}}; // invalid
所有版本的C和C ++都禁止以这种方式初始化指针(或示例中的指针数组)。
从技术上讲,使用字符串文字初始化指针的能力实际上是反常现象,而不是禁止使用数组初始化指针。 C引入对字符串文字的豁免是历史性的原因(在C的早期,很早在K&R C之前,字符串文字也不能用于初始化指针)。
答案 1 :(得分:0)
关于您的第一个问题,letters[0]
的类型为const char * const
。这是指向字符的指针,而不是字符本身。将指向字符的指针传递到std::cout
时,它将把它视为NUL终止的C字符串,并写出从所指向的内存开始直到遇到NUL字节的所有字符。这就是为什么输出将为A+
的原因。您可以通过编写以下命令自己传递第一个字符串的第一个字符:
std::cout << letters[0][0];
指针和/或C字符串本身是const的事实在这里无关紧要,因为没有任何内容可写给它们。
关于第二个问题,const char * const
声明了一个数组,但是您在该语句的右侧提供了一个嵌套数组。如果您确实想要两个字符数组,请输入:
const char *const letters[] = {{'A', '+', '\0'}, {'A', '\0'}};
那等于您的代码中第一个问题。或者,如果您想要一个数组:
const char *const letters = {'A', '+', '\0', 'A', '\0'};
该行等于:
const char *const letters = "A+\0A";