【问题标题】:Why are function parameters of type size_t?为什么函数参数是 size_t 类型的?
【发布时间】:2023-04-03 19:55:01
【问题描述】:

memset 的原型是void *memset(void *s, int c, size_t n);。那么为什么第三个参数的类型是 size_t 呢? memset 只是一个例子,我想要更一般的原因。提前致谢。

【问题讨论】:

标签: c


【解决方案1】:

size_tsizeof 运算符的返回类型,用于描述内存大小。对于memset,它指定了内存块(s)中的字节数(n)应该设置为给定值(c)。

size_t 的位大小因目标平台的地址空间而异。它并不总是与寄存器大小相关。例如,在分段内存架构中,sizeof (size_t) 可以小于sizeof (void *)。通常,size_t 在 32 位机器上是 4 个字节,在 64 位机器上是 8 个字节,等等。

【讨论】:

  • 你能解释一下为什么sizeof (size_t) can be smaller than the sizeof (void *)吗?非常感谢;)
  • 在分段内存中,每个段的大小小于总内存大小。例如,在 80286 中,您可以寻址 2^24 个总字节,但只能在每个段中使用 2^16 个连续字节。请参阅en.wikipedia.org/wiki/Memory_segmentation 现在,我手边没有带有 C99 编译器的 80286,但我猜想 sizeof (size_t) == 2 和 sizeof (void *) == 4。
  • 那么当我尝试在 80286 中 memset 2^20 字节时会发生什么?虽然它太大了,但我认为这是有道理的,因为我们可以处理 2^24 字节。
  • 在这种情况下,您将溢出size_t 变量而不是memset 任何字节,因为(1 << 20) % (1 << 16) == 0
  • 只能memset 2^16 字节而不是2^20 或2^24 的原因是必须将段偏移寄存器更改为超过64 kB。否则,地址将返回到开头。为了防止这种情况,使用 16 位 size_t 和 32 位 void * 是有意义的。请注意,C 支持不同的指针类型来处理分段架构(“近、远和巨大”:en.wikipedia.org/wiki/Intel_Memory_Model)。
【解决方案2】:

size_t 是用于表示对象大小的类型。在 C 中,整数类型(intlong 等)的大小取决于实现,您需要在每个编译器实现上使用正确的类型p,以便大小足以存储所有可能的值。

平台 SDK 附带的标头将有一个 typedef,它将 size_t 映射到正确的整数类型。因此,您只需编写一次memset(),它就会在每个实现中正确编译。

【讨论】:

    【解决方案3】:

    size_t 是一种适合表示数据对象所需内存量的类型。为无符号整数类型(一般为typedef unsigned int size_t;)。

    阅读this链接了解更多信息。

    【讨论】:

    • 这不是真的。在许多(如果不是大多数)64 位平台上,unsigned int 是 32 位,而 size_t 是 64 位。
    【解决方案4】:

    size_t 保证足够大以容纳所有平台上的指针。

    【讨论】:

    • 见梅加登法官的回答。
    • 是的,如果 size_t 足够大以引用所有内存,生活会更轻松。但是 Maygarden 法官所说的“sizeof (size_t) 可以小于 sizeof (void *)”是什么意思? (void *) 不是最大的指针吗?
    • 他有一个很好的观点,但这不是他最初所说的:他在编辑中添加了这一点。不过他是对的:size_t 只保证能够访问分段架构的给定存储库中的所有内存。很长一段时间以来,程序员都不必担心这个问题:)
    • 甚至可能有 no 整数类型大到足以容纳最大的指针类型。 C99 定义了(可选的)intptr_tuintptr_t 类型,它们大到足以容纳任何对象指针(即不是函数指针),包括 void *。同时size_t 只需要足够大就可以代表,顾名思义,大小。例如,考虑一个分段架构,其中“远”指针可能指向当前段之外的内存,但指向的内存区域必须适合单个段;指针可以是 32 位,带有 16 位 size_t
    • 我相信 IA-32 处理器仍然支持实模式。因此,针对 8086 寻址模式的编译器可能会发生这种情况。 AMD64 不推荐使用段寄存器。但是,是的,我们大多是迂腐的。这就是为什么我没有拒绝你的答案。尽管根据 C 标准,它在技术上是不正确的。
    猜你喜欢
    • 2012-06-15
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 2019-12-26
    • 1970-01-01
    • 2012-12-21
    • 2021-12-31
    相关资源
    最近更新 更多