C - 为什么即使目标缓冲区为零,strncpy 也能复制源字符串?


int main() {
char src[] = "santosh";
char dest[0];
strncpy(dest, src, 4);
printf("%sn", 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 不够,也能复制源字符串?

您的代码调用未定义的行为,试图解释为什么它会产生一些输出或其他输出是没有意义的。

以下是问题:

  • 您不包括<stdio.h>,也不包括<string.h>。调用以前未定义的函数是不行的。 包含正确的头文件以避免未定义的行为。

  • char dest[0];定义了一个大小为0的数组。无法访问这样的对象,甚至它的地址也没有意义。gccclang允许这样做,但作为C标准的扩展。 这个定义看起来像一个错别字,使用gcc -Wall -Wclang -Weverything来启用有用的警告,以防止这种愚蠢的错误。

  • strncpy(dest, src, 4);调用未定义的行为,因为dest的长度小于4。请注意,如果dest长度为4,则行为仍然容易出错,因为如果源字符串的长度大于或等于 size 参数,strncpy不会 null 终止目标数组。这里"santosh"的长度是7,所以dest可以保存字符sant,但没有空终止符。 您的while循环将调用未定义的行为,因为while (dest[i])将访问超出其大小的deststrncpy()容易出错,它的语义被广泛误解,很容易导致错误。请勿使用此功能

  • 如上所述,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 = '';
strncat(dest, src, 4);
printf("%sn", 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("%sn", 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;
}

相关内容

  • 没有找到相关文章

最新更新