(免责声明:此答案仅涵盖 C++。不建议同时要求 C 和 C++,因为两种语言完全不同)
序幕
char *k ;
这声明了一个指向字符的指针。
"ddddd"
这个表达式的类型char const[6]
是 ,即一个由六个常量字符组成的数组。这种类型的表达式可以隐式转换为指向数组第一个元素的指针。该指针的类型是char const*
,即指向常量字符的指针。Achar const*
不能转换为 a char*
,因为char*
它允许修改它指向的字符,而char const*
不允许修改。
char *d="ddddd";
由于上述规则,这种说法是不正确的。您应该打开编译器上的警告,它会警告您不要这样做(理想情况下它实际上是一个错误,而不仅仅是一个警告)。char const* d = "ddddd";
如果你真的想要一个指针或者char d[] = "ddddd";
你想要一个数组,它应该是。第二种形式不需要const
,因为它会制作副本,因此不会冒更改原始数据的风险,即const
.
*d
这个表达式涉及到上面提到的隐式转换char const*
,然后*
对它应用间接运算符(the),从而产生一个类型为 的表达式char const&
,即对常量字符的引用。
*k
与 类似*d
,这对指针执行间接操作。在这种情况下,k
是 type char*
,所以结果表达式是 type char&
。
*k=*d; //expecting to copy "ddddd" to *k
赋值分配单个字符,因为它是从对常量字符的引用到对字符的引用的赋值。它最终将字符串的第一个字符分配给 指向的字符k
,即……等等。
k
指向哪里?它从未初始化!这注定以悲剧收场。
第1章
那么,我们如何k
指向某个地方呢?我们如何将整个字符串从该空间复制d
到该空间中?
要将d
数组的六个字符复制到中k
,我们需要六个字符的空间。最简单的方法是创建一个包含六个字符的数组。
char k[6];
现在,如何复制这六个元素?我们可以使用 C 库函数strcpy
,它复制以空字符结尾的字符串。使用此功能需要非常小心,因为:
它要求源有一个 null ( '\0'
) 字符标记结束;如果源没有这样的字符,则行为未定义,任何事情都可能发生。这就是字符串"ddddd"
有六个字符而不是 5 个的原因:\0
编译器会在末尾为您插入一个隐式字符。
它要求目标有足够的空间容纳包括 空终止符在内的整个源字符串。如果目的地没有足够的空间,则行为也未定义,任何事情都可能发生。
这就是如何使用此函数来制作字符串的副本:
std::strcpy(k, d);
未能满足第 1 点或第 2 点可能会导致任何事情,从程序看似正常工作(如果你不走运),到以奇怪的方式随机运行,再到简单地崩溃(如果你幸运的话)。
结语
伙计,这是很多信息。C++ 程序员必须一直关心这些问题吗?那一定很烦人。
好吧,C++ 程序员可以使用std::string
字符数组来代替字符数组,这样就少了很多麻烦:我们可以使用赋值运算符进行复制,我们不需要跟踪正确的大小,我们不需要关心是否有 null终止符到位,我们不需要在编译时限制大小,还有很多其他优点。
std::string k;
void ffill()
{
std::string d="ddddd";
k = d;
cout<<k<<"\n";
d[1]=5;
cout<<k<<"\n";
}