使用strncpy时堆栈出现奇怪的行为

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;
}

我可以得到我所期望的。

为什么会发生这种情况?是因为堆栈和堆吗?它究竟如何产生如此巨大的差异?


你遇到了什么编译器错误?代码看起来是正确的。 - Armen Tsirunyan
这段代码编译得很好。你确定你没有犯其他的笔误吗? - templatetypedef
我正在使用http://ideone.com/ 进行编译,但它显示无法编译。我仍然有点困惑,我的电脑也没有gcc编译器。有人可以帮我编译或给我一些帮助吗?非常感谢。 - windsound
哦,我的错。我使用堆栈的方式会导致没有输出。printf语句没有起作用。 - windsound
3
有些情况下,你确实需要使用strncpy()函数,但这并不是其中之一。请参考man 3 strncpy了解其详细信息。 - wildplasser
是的,这实际上是一个课堂练习,我应该让strncpy函数工作并看看它的运作方式。 - windsound
3个回答

6
问题 - 在这两种情况下 - 是当您调用 strncpy 后,您的字符串不会被正确终止。
您指定要复制 2 个字符,而源字符串 in 的长度为4。因此,strncpy 将复制2个字符,并且由于它小于源字符串的长度,因此不会添加任何空结束符 - 要了解为什么如此,请查看 strncpy 的文档如果在复制整个字符串 src 之前达到计数,则生成的字符数组不以 null 结尾。 在这种情况下,您需要:
str[2] = '\0';

在使用'strncpy'函数之后:

第二种情况看起来可以正常工作,因为你从'malloc'中获取的缓冲区恰好被初始化为全部为零,但你不应该依赖于这一点。

请查看strncpy的文档,注意null终止符的例外情况,并且一般情况下需要小心处理字符串终止符!

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


1
我认为他会想要 str[2] = 0,而不是 str[3] = 0。 - Armen Tsirunyan
好的,它仍然像以前一样,它是合规的,但没有任何输出。 - windsound

5
代码编译正常。运行时错误可能是因为您没有使用 null 结束 str。根据 man 手册,strncpy() 类似于 strcpy(),但最多只复制 n 个字节。如果在前 n 个字节中没有 null 字节,则放入 dest 的字符串将不会以 null 结尾。请在 strncpy() 后添加 str[2]=0;

我得到的结果是:http://ideone.com/2V0ZE#view_edit_box 它可以工作,但无法打印任何内容。为什么会这样呢? - windsound
应该是 str[2]=0; 或者 str[2]='\0'; 双引号用于字符串字面量。 - P.P
非常感谢。我犯了很多错误。我应该删除这篇帖子吗?我已经修复了。 - windsound

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'; 也是一个有效的解决方案。


谢谢你的帮助,其实我最大的错误是第二版中使用了双引号而非单引号。这个愚蠢的错误导致了问题 XD - windsound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接