char *k ;
void ffill()
{
char *d="ddddd";
*k=*d; //expecting to copy "ddddd" to *k
cout<<k<<"\n";
*d[1]=5; // trying to change array element
cout<<k<<"\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
ffill();
cout<<k<<"\n";
}
过程填充在局部变量的帮助下初始化字符数组k。我不确定它复制"ddddd"
变量指针(这是错误的,因为在自动销毁d存储器后不安全)或者它复制了值并且在*k
被正确初始化之后。
如何使用*d
数组元素?编译器对*d[1]=5;
答案 0 :(得分:17)
(免责声明:这个答案仅涵盖C ++。不建议同时要求C和C ++,因为两种语言都完全不同)
char *k ;
这声明了一个指向角色的指针。
"ddddd"
此表达式具有类型char const[6]
,即六个常量字符的数组。可以将此类型的表达式隐式转换为指向数组第一个元素的指针。该指针的类型是char const*
,即指向常量字符的指针。 char const*
无法转换为char*
,因为char*
允许修改其指向的字符,而char const*
则不允许。
char *d="ddddd";
由于上述规则,此声明不正确。您应该打开编译器上的警告,它会警告您不要这样做(理想情况下它实际上是一个错误,而不仅仅是一个警告)。如果你真的想要一个指针,它应该是char const* d = "ddddd";
,如果你想要一个数组,它应该是char d[] = "ddddd";
。第二种形式不需要const
,因为它会复制,因此不会有更改原始数据的风险,即const
。
*d
此表达式涉及到上面提到的char const*
的隐式转换,然后将间接运算符(*
)应用于它,从而生成类型为char const&
的表达式,即,对常数字符的引用。
*k
与*d
类似,它对指针执行间接寻址。在这种情况下,k
的类型为char*
,因此生成的表达式的类型为char&
。
*k=*d; //expecting to copy "ddddd" to *k
赋值分配单个字符,因为它是从 a 常量字符的引用到 a 字符的引用。它最终将字符串的第一个字符分配给k
指向的字符,即......等待。
k
指向哪里?它从未被初始化!这必将以悲剧告终。
那么,我们如何让k
指向某个地方?我们如何将整个字符串从d
复制到该空间?
要将d
数组的六个字符复制到k
,我们需要六个字符的空格。最简单的方法是只创建一个包含六个字符的数组。
char k[6];
现在,如何复制六个元素?我们可以使用C库函数strcpy
,它复制以null结尾的字符串。这个功能需要很多使用,因为:
它要求源标记结尾的空('\0'
)字符;如果源没有这样的字符,则行为是未定义的,任何事情都可能发生。这就是字符串"ddddd"
有六个字符而不是5的原因:编译器为您插入的末尾有一个隐式\0
字符。
它要求目标为整个源字符串提供足够的空间,包括空终止符。如果目标没有足够的空间,则行为也是未定义的,任何事情都可能发生。
这是如何使用此函数来制作字符串的副本:
std::strcpy(k, d);
如果没有遇到#1或#2点,可能会导致任何事情,从看似正在运作的程序(如果你运气不好),以奇怪的方式随机行动,简单地崩溃(如果你很幸运)。< / p>
男人,这是很多信息。 C ++程序员是否必须始终关注这些问题?那一定很烦人。
好吧,C ++程序员可以使用std::string
而不是字符数组,并且可以减少麻烦:我们可以使用赋值运算符进行复制,我们不需要跟踪正确的大小,我们不要需要关注空终止符,我们不需要在编译时限制大小,以及其他一些优点。
std::string k;
void ffill()
{
std::string d="ddddd";
k = d;
cout<<k<<"\n";
d[1]=5;
cout<<k<<"\n";
}
答案 1 :(得分:1)
使用C编程语言,您应该使用数组而不是指针(因为它可能指向只读字符串)。例如:
char *k;
void
fill(void)
{
char d[] = "ddddd";
k = d;
d[1] = '5'; // Did you mean '5' ?
}
答案 2 :(得分:1)
就像Martinho Fernandes已经说过的那样:看起来你正在尝试使用'std:string'而不是char数组。
char k[20] ; //*k doesn't allocate any memory for you to use.
void ffill()
{
char *d="ddddd"; //This works, since it points to the constant character string in your code. But it can not be altered in any way. (It's a 'const char *')
strcpy(k, d); //This standard function copies the content of one pointer to another.
cout<<k<<"\n"; //Not too sure, but it should work,
k[1]=5; //k is the 'changeable memory, not 'd'.
cout<<k<<"\n";
}
答案 3 :(得分:1)
这里有几件你需要注意的事情。让我试着解释一下:
char *k ;
这一行声明了一个名为k
的变量,它是一个指向字符的指针。但是,它没有初始化为指向任何东西。尝试使用未初始化的指针将导致未定义的行为。
void ffill()
{
char *d="ddddd";
此行声明一个名为d
的变量,它也是一个指向字符的指针。同时,将指针初始化为指向包含5'd字符和终止NULL字符的常量字符数组(也称为c字符串)(因此数组有6个元素)。
*k=*d; //expecting to copy "ddddd" to *k
此行使用解除引用运算符(*)。此运算符复制d
指向的字符,并将其放在k
指向的地址处。如上所述,由于指针k
中的地址尚未初始化,因此会导致未定义的行为。
cout<<k<<"\n";
*d[1]=5; // trying to change array element
首先,您尝试将int分配给char。 C和C ++都允许这样做,但你可能无法得到你所期望的。在这种情况下,您尝试将第二个“d”字符替换为字符代码5.在ASCII中,这是一个非打印字符。
此外,由于d
指向c-string常量,因此尝试更改其元素会导致未定义的行为。
cout<<k<<"\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
ffill();
cout<<k<<"\n";
}
将一个c-string复制到另一个c-string还有一些其他问题,但这是我将在这里详述的所有细节。正如其他人所提到的,使用std :: string更简单。但是,我也相信学习如何使用c-strings非常有教育意义,可以提高你的编码技巧。
答案 4 :(得分:0)
您需要将d
声明为数组,而不是指针。:
char d[]
d[1] = '5'; // d is a char array, so did you mean the character '5'?
改变
*k=*d;
至k = d; //This will copy the value of the pointer
答案 5 :(得分:0)
让我们看看:
*k=*d; //expecting to copy "ddddd" to *k
这不会复制“字符串”,只会尝试将k
指向的内存设置为d
的第一个字符。如果没有初始化,那么它将会严重失败。
*d[1]=5; // trying to change array element
这也将失败。首先,这是双重间接。 d[1] = 5;
会打赌,但也会失败,因为字符串很可能存储在只读内存中。
改用字符串。