【问题标题】:Why memory functions such as memset, memchr... are in string.h, but not in stdlib.h with another mem functions?为什么 memset、memchr 等内存函数在 string.h 中,而在 stdlib.h 中却没有另一个 mem 函数?
【发布时间】:2012-04-04 15:27:30
【问题描述】:

我想知道,为什么这样的功能:
-memset
-memmov
-memchr
-memcpy

存在于string.h头文件中,但不存在于stdlib.h文件中,其中还有其他标准内存函数如动态内存分配:malloc、calloc、realloc、free。

也许将它们合并到一个标题中会更好?你怎么看待这件事? 我不明白,为什么一组内存函数与其他函数分开并存在于字符串头(string.h)中。

【问题讨论】:

  • 这看起来像是您正在使用的 C 库的实现问题。其他 C 库可能会选择将 memcpy 移动到 stdlib。
  • malloc 和家族处理动态内存分配。 memcpy 和家族处理字节序列。 strcpy 和家族也处理字节序列,但方式略有不同。
  • @AgA:如果 C 库符合 ISO 标准,那么 memcpy 将位于 string.h,而不是 stdlib.h
  • 我猜,纯属历史原因。这可能是函数首次引入时放入的头文件,为了保持最大的向后兼容性,标准委员会决定让它们保留在那里。
  • C 标准库不是一致设计的模型。

标签: c function memory header


【解决方案1】:

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

(C99, 7.21.1p1) 标题 声明了一种类型和几个函数,并定义了一个宏,可用于操作字符类型数组和其他被视为数组的对象 字符类型。

【讨论】:

  • 但是诸如 memset、memchr、memmov、memcpy 之类的方法可以使用 void* 类型,而且实际上更多的工作内存不是 char,对吗?
  • 您可以传递任何对象指针类型,但数组元素实际上被解释为它们具有unsigned char 类型。 (C99, 7.21.1p3)
  • 另外关于void *,注意在K&R C (pre-Standard C)中,没有void类型并且像memcpymemset这样的函数的参数是@987654329 @type 而不是void *.
【解决方案2】:

我不会真的认为string.h 函数是“记忆”函数。相反,我会将它们视为“数组”函数,因为它们对包含在内存序列中的数据进行操作。相比之下,malloc(和其他人)实际上提供了内存服务,例如分配,而不是操作内存区域内的数据。

特别是,string.h 中的函数不负责任何内存分配或释放,或任何形式的内存管理。即使是像char * strerror(int) 这样看似创建一个全新字符串的函数,也不会进行任何分配,因为返回值实际上是一个静态分配的字符串。其他函数可能会返回一个指向内存块的指针,但这实际上只是它们的参数之一(例如memcpy)。或者它们返回一个指向子字符串开头的指针 (strtok),或者一个表示比较的整数 (memcmp)。

另一方面,stdlib.h 也与内存无关。 stdlib.h 的设计是提供大量程序可能需要的通用操作。记忆功能恰好是这种基本操作的例子。但是,exitsystem 等其他函数也是很好的示例,但不适用于内存。

现在stdlib.h 中有一些功能,IMO 本来可以放在string.h 中,特别是各种转换功能(mbstowcswcstombsatoistrtod 等),以及甚至可能是 bsearchqsort 函数。这些函数遵循与string.h 函数相同的原则(它们对数组进行操作,不返回新分配的内存块等)。

但是从实际的角度来看,即使将mem* 函数与mallocrealloccallocfree 函数结合起来很有意义,C 标准库也是 永远不会像这样重组。这样的更改肯定会破坏代码。此外,stdlib.hstring.h 已经存在了很长时间,它们都是非常有用和基础的库,因此这些更改可能会破坏大多数(或至少很多)C 代码。

【讨论】:

    【解决方案3】:

    在 Pre-Standard C 中,这些函数确实是在其他地方定义的,但既不在 stdlib.h 也不在任何其他标准头文件中,而是在 memory.h 中。它可能仍然存在于您的系统上,它肯定仍然存在于 OS X 上(截至今天)。

    memory.h 在 OS X 10.11 上(没有许可证头):

    #include <string.h>
    

    整个文件只有#include'ing string.h,以保持与Pre-Standard C程序的向后兼容性。

    【讨论】:

      【解决方案4】:

      除了历史考虑之外,当您考虑没有给定操作系统的上下文时,将 string.h 中的数据操作实用程序和 stdlib.h 中的 malloc 等系统功能分开是很有意义的。嵌入式系统可能有也可能没有 RTOS,它们可能有也可能没有可用的标准内存分配。但是,像strcpymemcpy 这样的实用程序占据了相似的空间,因为它们不依赖任何外部系统,因此可以在任何可以运行编译代码的上下文中运行。从概念上和实践上来说,将它们放在一起并将它们与更复杂的系统调用分开是有意义的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-19
        • 2020-09-12
        • 2013-09-04
        • 2022-01-08
        • 1970-01-01
        • 2014-03-03
        • 2014-03-29
        相关资源
        最近更新 更多