4

我发现了一个非常有趣的问题。

当我使用以下代码时:

int main() {
    char * in = "hi, ";
    char str[10];
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

我的结果是什么,printf没有工作。

但如果我使用这个:

int main() {
    char * in = "hi, ";
    char * str = malloc(sizeof(char) * 10) ;
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

我能得到我所期望的。

为什么会这样?是因为堆栈和堆吗?这究竟是如何产生如此巨大差异的呢?

4

3 回答 3

6

问题 - 在这两种情况下 - 是在您调用strncpy.

您指定2复制字符,并且源字符串in的长度为 4。因此strncpy将复制 2 个字符,并且由于它小于源字符串的长度,因此不会添加空终止符 - 要了解为什么会这样,请查看strncpy的文档:

If count is reached before the entire string src was copied, the resulting character array is not null-terminated.

在这种情况下,您需要:

str[2] = '\0';

在'strncpy'之后。

第二种情况似乎可行,因为您从中获取的缓冲区malloc恰好被初始化为全零,但您不应该依赖它。

请查看strncpy 的文档,注意空终止的异常,一般来说,要小心字符串终止!

有关更多详细信息,请参阅:为什么 C++ 中的字符串通常以 '\0' 结尾?

于 2012-06-11T20:54:59.343 回答
5

代码编译得很好。运行时错误可能是因为您没有str用 null 终止。

从手册页:

strncpy() 函数类似,只是最多复制 n 个字节的 src。警告:如果 src 的前 n 个字节中没有空字节,则放在 dest 中的字符串不会以空值结尾。

在. str[2]=0;_strncpy()

于 2012-06-11T20:55:10.310 回答
1

您可以用零初始化内存以处于“安全”端。

看看下面的代码,

int main() {
    char * in = "hi, ";
    char str[10]={0};    
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

int main() {
    char * in = "hi, ";
    char * str = calloc(10,sizeof(char));
    strncpy(str, in, 2);
    printf("output = %s", str);
    free(str);      //<<Important step
    return 0;
}

str[2] = '\0';也是一个有效的解决方案。

于 2012-06-12T04:51:32.777 回答