字符串文字到 char 数组的转换如何在C++中实际工作
How does conversion of string literals to char arrays actually work in C++?
我试图了解指针,数组和字符串文字如何在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','+',' '},{'A',' '}};
抛出
error: braces around scalar initializer for type ‘const char* const’
const char* const letters[] = {{'A','+',' '},{'A',' '}};
^
谢谢!
该标准指定字符串文本 - 就您的程序而言 - 表示为静态存储持续时间的const
字符数组,带有尾随' '
终止符。 该标准没有指定编译器如何实现此效果,只是您的程序可以以这种方式处理字符串文字。
因此,要么阻止修改字符串文字(例如,将字符串文字传递给期望char *
的函数是一个可诊断的错误,并且代码将无法编译),要么 - 如果代码围绕类型系统修改字符串文字中的任何字符 - 涉及未定义的行为。
在您的示例中,letters[0]
的类型为const char *
,其值等于字符串文本"A+"
中第一个字符的地址。
std::cout
,属于std::ostream
型,有一个接受const char *
的operator<<()
。 此函数由语句std::cout << letters[0]
调用,该函数假定const char *
点为零终止的char
数组。 它遍历该数组,单独输出每个字符,直到遇到尾随' '
(不输出)。
问题是,const char *
意味着指针指向const char
,而不是指针不能更改(那将是char * const
)。 因此,可以增加指针,但不能更改它指向的值。 所以,如果我们这样做
const char *p = letters[0];
while (*p != ' ')
{
std::cout << *p;
++p;
}
它循环访问字符串文字"A+"
的字符,单独打印每个字符,并在到达' '
时停止(上面产生相同的可观察输出std::cout << letters[0]
)。
但是,在上面
*p = 'C';
不会编译,因为p
的定义告诉编译器*p
无法更改。 但是,仍允许递增p
。
原因
const char* const letters [] = {{'A','+',' '},{'A',' '}};
不编译的是数组初始化器不能用于初始化指针。 例如;
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之前,字符串文字也不能用于初始化指针)。
至于你的第一个问题,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', '+', ' '}, {'A', ' '}};
这等于你的代码形式第一个问题。或者,如果您想要单个阵列:
const char *const letters = {'A', '+', ' ', 'A', ' '};
该行等于:
const char *const letters = "A+ A";
- QSqlquery prepare()和bindvalue()不工作
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 用于了解输入和输出流缓冲区实际工作方式的程序
- 有人可以解释速记赋值运算符的实际工作原理吗?
- 字符串文字到 char 数组的转换如何在C++中实际工作
- `std :: string :: find_last_of()如何实际工作
- 对等如何实际工作网络/端口明智
- Ctrl Z的实际工作方式
- 浮点计算在 C++ 中是如何实际工作的
- 噪声功能的实际工作原理
- 转换构造函数的实际工作方式
- 栅栏是如何在c++中实际工作的
- 如何检查驱动程序代码签名策略是否已启用并实际工作
- 在C++参数中的引用和指针如何实际工作?他们的固定协议/"rule"是什么?
- 带循环的宏是如何在C/C++中实际工作的
- 依赖于其他 slib 的静态库是否需要它们的实际'code'才能工作?
- C++:将WCHAR转换为LPCWSTR - 实际工作示例