int main() {
char src[] = "santosh";
char dest[0];
strncpy(dest, src, 4);
printf("%s\n", dest); // expecting o/p "sant" but o/p was "santtosh"
int i = 0;
while (dest[i]) {
printf("%c", dest[i]); //expecting output "sant" but it was "santtosh"
i++;
}
printf("\n");
i = 0;
while (src[i]) {
printf("%c", src[i]); // expecting o/p "santosh" but it was "anttosh"
i++;
}
return 0;
}
我遇到了这段代码的问题,我使用gcc编译器运行代码,这是我得到的输出(评论部分)。为什么行为不符合预期?为什么strncpy()
能够复制源字符串,即使dest buff不够?
答案 0 :(得分:1)
您的代码调用未定义的行为,尝试解释为什么它会产生某些输出或另一个是没有意义的。
以下是问题:
您不包括<stdio.h>
,也不包括<string.h>
。调用之前未定义的函数不正常。包括正确的头文件以避免未定义的行为。
char dest[0];
定义了一个大小为0
的数组。无法访问此类对象,即使其地址有意义也无法访问。 gcc
和clang
允许这样做,但作为C标准的扩展。这个定义看起来像一个拼写错误,使用gcc -Wall -W
或clang -Weverything
来启用有用的警告,以防止出现这种愚蠢的错误。
strncpy(dest, src, 4);
调用未定义的行为,因为dest
的长度小于4
。请注意,如果dest
的长度为4
,则行为仍然容易出错,因为如果源字符串的长度大于或等于size参数,strncpy
将不为null终止目标数组。此处"santosh"
的长度为7
,因此dest
将包含字符s
,a
,n
和t
,但没有空终止符。您的while
循环将调用未定义的行为,因为while (dest[i])
将访问超出其大小的dest
。 strncpy()
容易出错,其语义被广泛误解,并且很容易导致错误。 请勿使用此功能。
如上所述,while (dest[i])
会调用未定义的行为,因为dest
无法取消引用为当前定义的,或者即使它被定义为char dest[4];
。
以下是使用snprintf()
和strncat()
的改进版本:
#include <stdio.h>
#include <string.h>
int main(void) {
char src[] = "santosh";
char dest[5];
*dest = '\0';
strncat(dest, src, 4);
printf("%s\n", dest); // will output "sant"
for (int i = 0; dest[i]; i++) {
printf("%c", dest[i]); // will output "sant" too
}
printf("\n");
snprintf(dest, sizeof dest, "%s", src);
printf("%s\n", dest); // will output "sant"
for (int i = 0; dest[i]; i++) {
printf("%c", dest[i]); // will output "sant" again
}
printf("\n");
for (int i = 0; src[i]; i++) {
printf("%c", src[i]); // will output "santosh"
}
printf("\n");
return 0;
}