为什么类似memset、memchr等内存函数在string.h中,而不是与其他内存函数一起在stdlib.h中?

69
我很好奇为什么像memset、memmov、memchr和memcpy这样的函数存在于string.h头文件中,而不是stdlib.h文件中。在stdlib.h中有其他标准内存函数(如动态内存分配:malloc、calloc、realloc和free)。也许将它们合并到一个头文件中会更好?你对此有何看法?我不明白为什么一组内存函数要与其他函数分开,存在于string.h头文件中。

1
这看起来像是您正在使用的C库的实现问题。其他C库可能会选择将memcpy移动到stdlib中。 - AgA
2
mallocеҸҠ其家ж—ҸеӨ„зҗҶеҠЁжҖҒеҶ…еӯҳеҲҶй…ҚгҖӮmemcpyеҸҠ其家ж—ҸеӨ„зҗҶеӯ—иҠӮеәҸеҲ—гҖӮ strcpyеҸҠ其家ж—Ҹд№ҹеӨ„зҗҶеӯ—иҠӮеәҸеҲ—пјҢдҪҶж–№ејҸз•ҘжңүдёҚеҗҢгҖӮ - n. m.
9
如果C语言库符合ISO标准,那么memcpy函数将在string.h中而不是stdlib.h中。 - Blastfurnace
1
我的猜测是,这纯粹是历史原因。当这些函数首次引入时,它们可能被放置在那个头文件中,为了保持最大的向后兼容性,标准委员会决定让它们留在那里。 - Some programmer dude
7
C标准库的设计并不一致。 - Keith Thompson
4个回答

43

实际上,string.h是一个定义为标准头文件的函数库,声明了一些处理字符数组而不仅仅是字符串的函数。像memcpymemset这样的函数接受的参数被视为指向类型为字符数组的对象的第一个元素的指针。

(C99, 7.21.1p1)头文件< string.h >声明了一个类型和多个函数,并定义了一个宏,用于操作字符类型的数组以及其他被视为字符类型数组的对象。


4
但是像memset、memchr、memmove、memcpy这样的方法使用的是void*类型,实际上更多地处理的是内存而不是字符,我的理解正确吗? - user1131997
3
你可以传递任何对象指针类型,但实际上数组元素被解释为 unsigned char 类型。(C99,7.21.1p3) - ouah
2
此外,关于void *,请注意,在K&R C(标准C之前),没有void类型,像memcpymemset这样的函数的参数是char *类型而不是void * - ouah

13
我认为 string.h 函数不应该被称为“内存”函数,而应该被称为“数组”函数,因为它们操作的是包含在内存序列中的数据。相比之下,malloc(及其他函数)实际上提供了内存服务,如分配,而不是操作内存区域内的数据。特别地,string.h 中的函数不负责任何内存分配、释放或任何形式的内存管理。即使像 char * strerror(int) 这样表面上创建一个全新字符串的函数也没有进行分配,因为返回值实际上是静态分配的字符串。其他函数可能会返回指向内存块的指针,但这只是它们的参数之一(例如 memcpy),或者返回指向子字符串开头的指针(strtok),或者表示比较结果的整数(memcmp)。
另一方面,stdlib.h 也不是真正关于内存的。设计 stdlib.h 的目的是提供大量程序可能需要的通用操作。内存函数只是这些基本操作的示例。然而,像 exitsystem 这样的其他函数也是很好的例子,但并不适用于内存。
现在,stdlib.h 中有一些函数,我认为它们本应该放在 string.h 中,特别是各种转换函数(mbstowcswcstombsatoistrtod 等),甚至可能是 bsearchqsort 函数。这些函数遵循与 string.h 相同的原则(操作数组,不返回新分配的内存块等)。

从实际角度来看,即使使用mallocrealloccallocfree函数与mem*函数相结合非常有意义,C标准库也永远不会像这样重新组织。这样的改变一定会破坏代码。另外,stdlib.hstring.h存在已久,都是如此有用和基础的库,改变可能会破坏大部分(或至少很多)的C代码。


4
在早期的C语言标准中,这些函数确实是在其他地方定义的,但既不在中,也不在任何其他标准头文件中,而是在中定义。它可能仍然存在于您的系统上,在OS X上肯定仍然存在(截至今天)。
OS X 10.11上的 (没有许可证头):
#include <string.h>

整个文件只包含了 #include 引用的 string.h,以保持与 Pre-Standard C 程序的向后兼容性。

2
除了历史考虑,将像string.h中的数据操作工具和stdlib.h中的malloc等系统函数分离在一起,在考虑操作系统不是给定的情况下,这是非常有意义的。嵌入式系统可能有也可能没有RTOS,并且可能没有标准的内存分配可用。然而,像strcpymemcpy这样的实用程序在概念上和实际上都占据着类似的空间,因为它们不依赖于任何外部系统,因此可以在任何可以运行编译代码的环境中运行。从概念上和实践上看,将它们放在一起并将它们与更复杂的系统调用分开是合理的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接