C语言 这条白线是干什么用的?

eivnm1vs  于 2023-03-01  发布在  其他
关注(0)|答案(3)|浏览(145)

我的任务是修复Larry Wall的原始补丁代码,使其能够在ANSI C中编译并进行调试。然而,我并不真正理解savestr函数中的代码做得如何好,足以修复它。

char *
savestr(s)
register char *s;
{
    register char  *rv,
                   *t;

    t = s;
    while (*t++)
    rv = malloc((MEM) (t - s));
    if (rv == NULL)
        fatal ("patch: out of memory (savestr)\n");
    t = rv;
    while (*t++ = *s++);
    return rv;
}

我的理解是savestr接受一个字符串参数并返回一个字符串。该函数创建了两个字符串,rv和t.,然后将t赋值为s。在那一行之后,我完全迷路了。有人能给我解释一下代码是做什么的吗?我尤其不明白while循环是如何沿着的,我不知道(t-s)是做什么的。
谢谢你对我的任何指导。

v1l68za4

v1l68za41#

char *
savestr(s)
register char *s;

这是一个旧的K&R style declaration/definition.
register关键字现在也完全过时了。它原本是编译器的优化提示。但现在已经不再需要了,除非在一些编译器无法优化的罕见情况下。

t = s;
while (*t++);
rv = malloc((MEM) (t - s));

t被赋值为s,并递增,直到它到达'\0'字节。t - s然后给出两个指针之间的差,这等效于strlen (s) + 1,然后为rv分配内存,与strdup()非常相似。

t = rv;

这会将rv的指针值赋给t,这样它们现在都指向同一个内存位置,在函数结束时,只有rv会指向这个位置。

while (*t++ = *s++);

解析为:

while ((*(t++) = *(s++)) != '\0');

在表达式中,后置增量运算符返回操作数的旧值。因此,它首先将s所指向的字符复制到t所指向的字符,然后将两个指针都递增,以指向它们各自的下一个字符。在循环中,这将由X1 M11 N1 X指向的存储器区域的内容复制到由X1 M12 N1 X指向的存储器区域。
错误是相当明显的,而且已经被指出了。所以我将把它留给OP去弄清楚。
savestr的现代版本如下所示:

char *
savebuf (char const *s, size_t size)
{
  char *rv;

  if (! size)
    return NULL;

  rv = malloc (size);

  if (! rv)
    {
      if (! using_plan_a)
    xalloc_die ();
    }
  else
    memcpy (rv, s, size);

  return rv;
}

char *
savestr (char const *s)
{
  return savebuf (s, strlen (s) + 1);
}

void
xalloc_die (void)
{
  fatal ("out of memory");
}

请注意ANSI样式函数声明/定义和register关键字的缺失。长度由调用方传递,第二个while循环已替换为memcpy()。宏MEM(最初计算为(unsigned))和指针t已被删除。

daolsyd0

daolsyd02#

t - s是大小(两个指针之间的差),并且通过语句t = swhile(*t++)实现strlen(s) + 1。
while (*t++ = *s++)s指向的值*复制到s指向的字符串,并递增两个指针。字符串以\0结束,\0为false,因此当复制\0时循环将终止。
所有这些都实现了strdup()
关键字register在当前的编译器上可能没有任何作用,而且,我认为(MEM)从ptrdiff_t(一个“有符号整数类型”(6.5.5))到malloc()所期望的size_t的转换是不需要的。

wkyowqbh

wkyowqbh3#

t和s是内存中的位置。t-s计算指针t和s之间有多少字节。while循环遍历t指向的任何字符串,每次遍历一个字符(慢慢地将t向下移动一个字节,直到t最终指向空字符--这是cstring的结尾)。
第二个while循环遍历s和t,并将s指向的值赋给t指向的内存,直到它们为null。当字符为null字符(\0 == 0)时,循环停止,因为0为false。
这并不是一个完整的演练,但是在您处理这个过程中,您可以随时提出更多的问题,我会做出回应。

相关问题