strncpy和memcpy有什么区别?

24

如何访问s中的s[7]

我没有观察到strncpymemcpy之间的任何区别。如果我想打印输出s,以及s[7](例如qwertyA),我需要在以下代码中进行哪些更改:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char s[10] = "qwerty", str[10], str1[10];
    s[7] = 'A';
    printf("%s\n", s);
    strncpy(str, s, 8);
    printf("%s\n", str);
    memcpy(str1, s, 8);
    printf("%s\n", str1);
    return 0;
}

输出:

qwerty
qwerty
qwerty

1
尝试在你的上述代码中交换memcpystrncpy,然后体验其中的区别。 - Linus Kleen
另一个区别是类型检查和返回的类型。在其他情况下很重要,但在这里不是。 - chux - Reinstate Monica
6个回答

50

其他人已经指出了你的空字符终止问题。在理解memcpystrncpy之间的区别之前,你需要了解空字符终止。

主要区别是,memcpy将复制您请求的所有N个字符,而strncpy将复制包括第一个空字符终止符在内的最多N个字符。

如果它复制的字符少于N个,它将用空字符填充其余部分。


11
还有一个不同点,strncpy会用0来填充剩余的空间。例如,如果你执行strncpy(a,b,255),并且a的长度为10,则strncpy将复制这10个字符,并用0填充其余240个字符的空间。 - nos
@nos:我已经意识到了,并进行了编辑。不过还是谢谢你 :) - Philip Potter
1
还要考虑的是:“如果源字符串的长度超过了num,目标字符串末尾不会自动添加空字符。因此,在这种情况下,不能将目标字符串视为以空字符结尾的C字符串(这样读取会导致溢出)。” - JohnyTex

8
您得到了输出querty,因为索引7是错误的(数组的索引从0开始,而不是1)。在索引6处有一个null-terminator,用于表示字符串的结尾,它之后的任何内容都没有影响。
您需要修复两件事情:
  1. s[7]中的7更改为6
  2. s[7]处添加一个空终止符
结果将是:
char s[10] = "qwerty";
s[6] = 'A';
s[7] = 0;

原始不工作修复的工作

关于 strncpymemcpy 的问题,它们的区别在于 strncpy 会为你添加一个空终止符。但是,前提是源字符串在 n 前面有一个空终止符。因此,在这里您需要使用 strncpy,但要非常小心。


4

Strncpy会复制指定字节数的字符串,包括NULL字符。而memcpy会复制指定数量的字节。

如果使用printf语句打印字符串时遇到NULL字符,它将停止打印。因此,如果打印单个字符,则只会显示该字符。

printf("\t%c %c %c\t",s[7],str[7],str1[7]);

输出

  7              7

2
当您拥有以下情况时:

char s[10] = "qwerty";

以下是数组中包含的内容:

s[0]  'q'
s[1]  'w'
s[2]  'e'
s[3]  'r'
s[4]  't'
s[5]  'y'
s[6]   0
s[7]   0
s[8]   0
s[9]   0

如果您想在字符串末尾添加一个'A',那么需要在索引6处进行操作,因为数组的索引从0开始。

 s[6] = 'A';

请注意,当您以这种方式初始化数组时,剩余空间将设置为0(一个nul终止符)。虽然在这种情况下不需要,但通常要注意需要使您的字符串以nul结尾。 例如:
char s[10];
strcpy(s,"qwerty");
s[6] = 'A';
s[7] = 0;

在上面的示例中,“qwerty”,包括它的nul终止符,被复制到s中。s[6]会覆盖该nul终止符。由于s的其余部分未初始化,我们需要使用s[7] = 0;添加一个nul终止符。

2
要制作“qwertyA”,需要设置s[6] = 'A's[7]='\0'。字符串从0开始索引,所以s[0] == 'q',并且它们需要以空字符结尾。

我不应该将s[7]更改为s[6]。如果我们将s[6]设置为'A',那么我们将得到所需的输出。 - user559208
3
你的意思是你不想要期望的输出吗?O_o - Philip Potter
@user559208: 当marcog写下“将s[6]改为s[7]”时,我认为他实际上想表达的是,不要写s[7],而应该写s[6]。此外,不要忘记对字符串进行空字符终止(将s[7]设为0'\0'),因为这有助于防止溢出错误的发生。 - Matt Ellen
你可能对那里的混淆是正确的。我已经尝试使措辞更清晰。 - moinudin
@marcog:现在更清楚了。同时,对于那个小错误的引用表示抱歉! - Matt Ellen

1
如Philip Potter所解释的那样,memcpy的主要区别在于它将复制您要求的所有n个字符,而strncpy将复制到第一个空终止符(包括该终止符)或n个字符为止。如果strncpy复制的字符数少于N个,则会用空字符填充其余部分。 下面的程序将回答您的问题:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char s[10] = "qwerty",str1[10];
    int i;
    s[7] = 'A';
    memcpy(str1, s, 8);
    for(i=0;i<8;i++)
    {
        if(str1[i]!='\0')
            printf("%c",str1[i]);
    }
    return 0;
}

输出:

qwertyA

执行下面的代码并检查差异,你可能会发现它很有用。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char s[10] = "qwer\0ty", str[10], str1[10];
    s[7] = 'A';
    printf("%s\n",s);
    strncpy(str,s,8);
    printf("%s\n",str);
    memcpy(str1,s,8);
    printf("%s\n",str1);
    for(int i = 0; i<8; i++)
    {
        printf("%d=%c,",i,str[i]);
    }
    printf("\n");
    for(int i = 0; i<8; i++)
    {
        printf("%d=%c,",i,str1[i]);
    }
    return 0;
}

输出:

qwer
qwer
qwer
0=q,1=w,2=e,3=r,4=,5=,6=,7=,
0=q,1=w,2=e,3=r,4=,5=t,6=y,7=A,

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