我的任务是修复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)是做什么的。
谢谢你对我的任何指导。
3条答案
按热度按时间v1l68za41#
这是一个旧的K&R style declaration/definition.
register关键字现在也完全过时了。它原本是编译器的优化提示。但现在已经不再需要了,除非在一些编译器无法优化的罕见情况下。
t
被赋值为s
,并递增,直到它到达'\0'字节。t - s
然后给出两个指针之间的差,这等效于strlen (s) + 1
,然后为rv
分配内存,与strdup()
非常相似。这会将
rv
的指针值赋给t
,这样它们现在都指向同一个内存位置,在函数结束时,只有rv
会指向这个位置。解析为:
在表达式中,后置增量运算符返回操作数的旧值。因此,它首先将
s
所指向的字符复制到t
所指向的字符,然后将两个指针都递增,以指向它们各自的下一个字符。在循环中,这将由X1 M11 N1 X指向的存储器区域的内容复制到由X1 M12 N1 X指向的存储器区域。错误是相当明显的,而且已经被指出了。所以我将把它留给OP去弄清楚。
savestr
的现代版本如下所示:请注意ANSI样式函数声明/定义和
register
关键字的缺失。长度由调用方传递,第二个while
循环已替换为memcpy()
。宏MEM
(最初计算为(unsigned)
)和指针t
已被删除。daolsyd02#
t - s
是大小(两个指针之间的差),并且通过语句t = s
和while(*t++)
实现strlen(s)
+ 1。while (*t++ = *s++)
将s
指向的值*
复制到s
指向的字符串,并递增两个指针。字符串以\0
结束,\0
为false,因此当复制\0
时循环将终止。所有这些都实现了
strdup()
。关键字
register
在当前的编译器上可能没有任何作用,而且,我认为(MEM)
从ptrdiff_t(一个“有符号整数类型”(6.5.5))到malloc()
所期望的size_t的转换是不需要的。wkyowqbh3#
t和s是内存中的位置。t-s计算指针t和s之间有多少字节。while循环遍历t指向的任何字符串,每次遍历一个字符(慢慢地将t向下移动一个字节,直到t最终指向空字符--这是cstring的结尾)。
第二个while循环遍历s和t,并将s指向的值赋给t指向的内存,直到它们为null。当字符为null字符(\0 == 0)时,循环停止,因为0为false。
这并不是一个完整的演练,但是在您处理这个过程中,您可以随时提出更多的问题,我会做出回应。