代码之家  ›  专栏  ›  技术社区  ›  LukeN

C奇怪的阵列行为

  •  6
  • LukeN  · 技术社区  · 16 年前

    strncmp 不是它看起来的样子 strlcpy 由于在我的操作系统(Linux)上不可用,我想我可以尝试自己编写。

    A. 使用 mempcpy mempcpy公司

    #include <stdio.h>
    #include <string.h>
    
    #define BSIZE 10
    
    void insp(const char* s, int n)
    {
       int i;
    
       for (i = 0; i < n; i++)
          printf("%c  ", s[i]);
    
       printf("\n");
    
       for (i = 0; i < n; i++)
          printf("%02X ", s[i]);
    
       printf("\n");
    
       return;
    }
    
    int copy_string(char *dest, const char *src, int n)
    {
       int r = strlen(memcpy(dest, src, n-1));
       dest[r] = 0;
    
       return r;
    }
    
    int main()
    {
       char b[BSIZE];
       memset(b, 0, BSIZE);
    
       printf("Buffer size is %d", BSIZE);
    
       insp(b, BSIZE);
    
       printf("\nFirst copy:\n");
       copy_string(b, "First", BSIZE);
       insp(b, BSIZE);
       printf("b = '%s'\n", b);
    
       printf("\nSecond copy:\n");
       copy_string(b, "Second", BSIZE);
       insp(b, BSIZE);
    
       printf("b = '%s'\n", b);
    
       return 0;
    }
    

    结果是:

    Buffer size is 10                    
    00 00 00 00 00 00 00 00 00 00 
    
    First copy:
    F  i  r  s  t     b     =    
    46 69 72 73 74 00 62 20 3D 00 
    b = 'First'
    
    Second copy:
    S  e  c  o  n  d          
    53 65 63 6F 6E 64 00 00 01 00 
    b = 'Second'
    

    您可以在内部表示中看到(线 insp() 有一些杂音混入其中,比如 printf() 在第一个副本后的检查中设置字符串格式,在第二个副本中设置一个外部0x01。

    字符串被完整地复制,并且它正确地处理了太长的源字符串(让我们忽略将0作为长度传递给 copy_string

    4 回复  |  直到 16 年前
        1
  •  4
  •   Martin Beckett    16 年前

    字符串的结尾用一个\0标记,后面的内存可以是任何内容,除非你的操作系统故意将其清空,否则它就是随机留下的垃圾。

    注意:在本例中,“问题”不在copy\u字符串中,您正是在复制10chars-但是主代码中“first”之后的内存是随机的。

        2
  •  2
  •   Francisco Soto    16 年前

    因为您不是在源代码大小处停止,而是在destiny大小处停止,destiny大小恰好比源代码大,所以您复制的是源字符串加上一点垃圾。

    您可以很容易地看到您正在复制源字符串,其终止符为空。但是由于您要复制10个字节,而且字符串“First”和“Second”都小于10个字节,因此您也要复制超出它们的额外字节。

        3
  •  1
  •   James McNellis    16 年前

    使用 memcpy(dest, src, n-1) dest 和 src 至少不是两者都是 n-1 长度。

    例如, First\0 第n-1页 (9) 其中的人物;超过字符串文字结尾的内存内容是未定义的,当您读取该内存时,程序的行为也是未定义的。

        4
  •  0
  •   Jerry Coffin    16 年前

    额外的“stuff”在那里,因为您已经将缓冲区大小传递给 memcpy . 它将复制那么多字符,即使源代码较短。

    我会做一些不同的事情:

    void copy_string(char *dest, char const *src, size_t n) { 
        *dest = '\0';
        strncat(dest, src, n);
    }
    

    不像 strncpy , strncat 被定义为按照大多数人的合理预期工作。