【问题标题】:Difference between strncpy and memcpy?strncpy 和 memcpy 的区别?
【发布时间】:2011-06-03 09:28:54
【问题描述】:

如何在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

【问题讨论】:

  • 尝试在上面的代码中交换memcpystrncpy。然后体验不同。
  • 另一个区别是类型检查和返回的类型。在其他情况下很重要,这里不重要。

标签: c memcpy strncpy


【解决方案1】:

正如 Philip Potter 所解释的,主要区别在于 memcpy 将复制您要求的所有 N 个字符,而 strncpy 将复制最多包含第一个空终止符或 N 个字符,以较少者为准。如果它复制的字符少于 N 个,它将用空字符填充其余部分。 执行以下代码并检查差异,您可能会发现它很有用。

#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,

【讨论】:

    【解决方案2】:

    其他人指出了您的空终止问题。在了解memcpystrncpy 之间的区别之前,您需要了解空终止。

    主要区别在于 memcpy 将复制您要求的所有 N 个字符,而 strncpy 将复制最多包含第一个空终止符或 N 个字符,以较少者为准

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

    【讨论】:

    • 还有另一个区别,strncpy 将用 0 填充其余空间。例如如果您执行strncpy(a,b,255); 并且 a 的长度为 10,则 strncpy 将复制这 10 个字符并用 0 填充剩余的 240 个字符。
    • @nos:我在你之前就意识到了这一点,并对其进行了编辑。但无论如何谢谢:)
    • 还要考虑:“如果 source 长于 num,则不会在目标末尾隐式附加空字符。因此,在这种情况下,不应将目标视为以空字符结尾的 C 字符串(阅读它这样会溢出)。”
    【解决方案3】:

    即使您指定了要复制的字节数,Strncpy 也会复制到 NULL,但 memcpy 会复制到指定的字节数。

    printf 语句将打印到 NULL,因此您将尝试打印单个字符,它会显示,

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

    输出

      7              7
    

    【讨论】:

      【解决方案4】:

      您将得到输出 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;
      

      Original not workingfixed working

      至于strncpymemcpy的问题,区别在于strncpy为你添加了一个空终止符。但是,只有源字符串在n 之前有一个。所以strncpy是你想在这里使用的,但要非常小心那个大的BUT。

      【讨论】:

        【解决方案5】:

        当你有:

        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;

        【讨论】:

          【解决方案6】:

          要制作“qwertyA”,您需要设置s[6] = 'A's[7]='\0'

          字符串从 0 开始索引,因此 s[0] == 'q',它们需要以空值结尾。

          【讨论】:

          • 我不应该将 s[7] 更改为 s[6]。如果我们将 s[6] 设置为“A”,那么我们将获得所需的输出..
          • @user 所以你说你想要想要的输出? O_o
          • @user559208:当marcog 写“将s[6] 更改为s[7]”时,我认为他实际上的意思不是写s[7],而是写s[6]。另外,不要忘记字符串的空终止(将s[7] 设置为0'\0'),因为这将有助于防止溢出错误蔓延。
          • 您可能对那里的困惑是正确的。我试图让措辞更清晰。
          • @marcog:现在更清楚了。另外,对于轻微的错误引用,我们深表歉意!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-15
          • 2013-05-09
          • 2018-07-12
          • 2010-12-04
          • 2014-03-01
          相关资源
          最近更新 更多