在glibc中strncpy实现过于复杂

时间:2014-06-18 06:27:51

标签: c glibc strncpy

我试图理解 string.h 函数。这是我自己的strncpy()

实现
char * my_strncpy(char *dst, const char* src, int n)
{
    char *orig = dst;
    const char *hold = src;
    int count = 0, remain = 0;
    while(*(hold++))
            count++;
    if ( n > count )
    {
            remain = n - count;
            n = count;
    }
    while(n--)
            *dst++ = *src++;
    while(remain--)
            *dst++ = '\0';
    return orig;
}

但是在查看glibc实现here时,我想知道为什么它太大而复杂。

我使用" 时间"测试了执行时间命令。两个功能几乎相同。
有人可以分享关于glibc strncpy()的知识以及我在my_strncpy()中缺少的知识。

1 个答案:

答案 0 :(得分:1)

从现代C编程的角度来看," Glibc"代码编写得非常糟糕。对于具有32位对齐的特定平台,它看起来像是过早优化的集合。如果编译器是垃圾,那么您必须以首选对齐为单位对字节进行分组,并一次将它们复制一个这样的单元。这就是代码看起来很奇怪的主要原因。

我猜这段代码可能是很久以前编写的,当编译器在优化代码方面更糟糕时,CPU对这类内容的硬件支持较少。他们在前缀到后缀增量之间来回切换的不一致,看似随机的方式也表明代码是为糟糕的编译器编写的。

除了早熟优化之外,代码是完整的意大利面条,没有明智的解释。完全没有评论也表明代码是由一个糟糕的程序员编写的。

总而言之,为什么他们以这种方式编写代码可能有也可能没有各种历史原因,但代码中有许多不良的编程习惯,不能被解雇为早熟优化

将该代码视为垃圾。


另请注意,strncpy功能主要已过时,应避免使用。 strncpy仅用于Unix中的古老字符串格式。 It was never intended to be a safe version of strcpy。相反,该函数很危险,并且由于意外丢失空终止而导致大量错误。

strncpy的标准规范也迫使它做很多毫无意义的事情,比如在你事先知道长度时检查空终止。此外,人们可能想知道在第一个\0之后填充剩余字符的人有多好\0。所有这些毫无意义的要求使得这个功能不必要地变慢。

所以在现代C代码中任何地方都没有理由使用strncpy。复制已知长度字符串的正确方法是:

memcpy(str1, str2, str2len + 1);