c++ - 将字符串文字转换为 char 数组实际上在 C++ 中如何工作?

标签 c++ arrays pointers string-literals

我想了解指针、数组和字符串文字在 C++ 中的工作方式。

假设我们有下面这行代码:

const char* const letters[] = {"A+","A"};

如果我没理解错的话,这个声明将字母声明为指向常量字符的常量指针数组。根据我的理解,编译器实际上会将每个字符串文字转换为以空字符结尾的 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'}}; ^

谢谢!

最佳答案

标准规定,就您的程序而言,字符串文字表示为 const 的数组。静态存储持续时间的字符,尾随 '\0'终结者。该标准未指定编译器如何实现此效果,仅指定您的程序可以以这种方式处理字符串文字。

因此,要么阻止修改字符串文字(例如,将字符串文字传递给期望 char * 的函数是可诊断的错误,代码将无法编译),要么 - 如果代码绕过类型系统修改任何字符在字符串文字中 - 涉及未定义的行为。

在您的示例中,letters[0]类型为 const char * , 并且其值等于字符串文字中第一个字符的地址 "A+" .

std::cout , 属于 std::ostream 类型, 有一个 operator<<()接受 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' 时停止(上面产生相同的可观察输出 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

都是非法的。相反,需要定义数组,而不是指针。

const int nums[] = {1,2,3};
const int nums2[][3] = {{1,2,3}, {4,5,6}};

所有版本的 C 和 C++ 都禁止以这种方式初始化指针(或您的示例中的指针数组)。

从技术上讲,使用字符串文字来初始化指针的能力实际上是异常的,而不是禁止使用数组初始化指针。 C 引入字符串文字豁免的原因是历史性的(在 C 的早期,远在 K&R C 之前,字符串文字也不能用于初始化指针)。

关于c++ - 将字符串文字转换为 char 数组实际上在 C++ 中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57645930/

相关文章:

c++ - 字符串没有传递给类函数

c++ - VisualStudio2008 上的 std::vector 似乎没有得到最佳实现 - 太多的复制构造函数调用

python - numpy 2d 数组(坐标)需要分配到 3D 数组中,分配给某个特定的 bin

C++结构数组初始化

c++ - 链表/vector 中的指针

c++ - 在 C++ 中通过引用传递三维数组

c++ - 简单的 netbeans C++ 项目无法编译

arrays - 在 O(1) 空间和 O(n) 时间中确定大小为 n 的数组中具有 0 到 n-2 范围内值的所有重复项

c++ - "(new Type [n]) + 1"返回什么?

c++ - 使用指向映射的指针从其键访问映射的值