Why do i first have to strcpy() before strcat()?
为什么此代码会产生运行时问题:
但这不是吗?
strcat将查找空终止符,将其解释为字符串的结尾,然后在其中附加新文本,覆盖过程中的空终止符,并在连接末尾写入新的空终止符。
1
| char stuff[100]; // 'stuff' is uninitialized |
空终止符在哪里? stuff未初始化,因此它可能以NUL开头,或者其中可能没有NUL。
在C ++中,您可以执行以下操作:
1
| char stuff[100] = {}; // 'stuff' is initialized to all zeroes |
现在您可以执行strcat了,因为'stuff'的第一个字符是空终止符,因此它将附加到正确的位置。
在C中,您仍然需要初始化'stuff',可以通过两种方法完成:
1 2 3 4
| char stuff [100]; // not initialized
stuff [0] = '\\0'; // first character is now the null terminator,
// so 'stuff' is effectively""
strcpy(stuff ,"hi"); // this initializes 'stuff' if it's not already. |
-
{}在C中不是有效的初始化器。
-
呸! 我错过了C标签。 谢谢。
-
不过,您应该可以执行char stuff[100] = {0};。
-
我更喜欢char stuff[100]="";进行初始化,尽管在大多数情况下,第一次分配是strcpy。
在第一种情况下,stuff包含垃圾。 strcat要求目标和源都包含正确的以空字符结尾的字符串。
将扫描stuff以查找终止的'\\0'字符,并开始复制"hi"。如果找不到它,它将在数组末尾运行,并且可能会发生任何不良情况(即行为未定义)。
避免问题的一种方法是这样的:
1 2 3 4
| char stuff [100];
stuff [0] = '\\0'; /* ensures stuff contains a valid string */
strcat(stuff ,"hi");
strcat(stuff ,"there"); |
或者,您可以将stuff初始化为空字符串:
它将用<零>填充stuff的所有100个字节(增加的清晰度可能值得解决任何较小的性能问题)。
因为stuff在调用strcpy之前未初始化。在声明stuff不是空字符串之后,它是未初始化的数据。
strcat将数据追加到字符串的末尾-也就是说,它将在字符串中找到空终止符,并在其后添加字符。未初始化的字符串不保证具有空终止符,因此strcat可能会崩溃。
如果要如下初始化stuff,则可以执行strcat:
1 2 3
| char stuff [100] ="";
strcat(stuff ,"hi");
strcat(stuff ,"there"); |
Strcat将字符串追加到现有字符串。如果字符串数组为空,则无法继续查找字符串('\\0')的结尾,这将导致运行时错误。
根据Linux手册页,简单的strcat通过以下方式实现:
1 2 3 4 5 6 7 8 9 10 11 12
| char*
strncat(char *dest , const char *src , size_t n )
{
size_t dest_len = strlen(dest );
size_t i ;
for (i = 0 ; i < n && src [i ] != '\\0' ; i ++)
dest [dest_len + i ] = src [i ];
dest [dest_len + i ] = '\\0';
return dest ;
} |
如在此实现中所看到的,除非dest初始化为正确的c字符串值,否则strlen(dest)将不会返回正确的字符串长度。您可能很幸运在char stuff[100];拥有一个第一个零值的数组,但是您不应该依赖它。
另外,我建议不要使用strcpy或strcat,因为它们会导致一些意想不到的问题。
使用strncpy和strncat,因为它们有助于防止缓冲区溢出。
-
不,strncpy()不是"更安全的" strcpy()。