6

在了解到两者strncmp都不是它看起来的样子并且strlcpy在我的操作系统(Linux)上不可用之后,我想我可以尝试自己编写它。

我找到了 libc 维护者 Ulrich Drepper 的一句话,他发布了strlcpy使用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

4 回答 4

4

字符串的结尾由 \0 标记,之后的内存可以是任何东西,除非您的操作系统故意将其空白,否则它只是留在那里的任何随机垃圾。

请注意,在这种情况下,“问题”不在 copy_string 中,您正在复制 10 个字符 - 但主代码中“第一”之后的内存只是随机的。

于 2010-05-14T18:58:05.750 回答
2

因为你没有停在源大小,你停在命运大小,它恰好大于源,所以你正在复制源字符串加上一些垃圾。

您可以很容易地看到您正在复制带有空终止符的源字符串。但是由于您要复制 10 个字节,并且字符串“First”和“Second”都短于 10 个字节,因此您还复制了多余的字节。

于 2010-05-14T18:58:37.903 回答
1

使用memcpy(dest, src, n-1)调用未定义的行为,如果destsrc不是至少n-1在长度上。

例如,First\0长度为 6 个字符,但您n-1从中读取了 (9) 个字符;字符串文字末尾之后的内存内容是未定义的,当您读取该内存时程序的行为也是如此。

于 2010-05-14T18:59:05.563 回答
0

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

我会做一些不同的事情:

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

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

于 2010-05-14T19:02:53.170 回答