代码之家  ›  专栏  ›  技术社区  ›  Chris Lutz

大小与uintptr

  •  240
  • Chris Lutz  · 技术社区  · 15 年前

    C标准保证 size_t 可以保存任何数组索引的类型。这意味着,逻辑上, 西泽特 应该能够保存任何指针类型。我在一些网站上看到,我在谷歌上发现这是合法的和/或应该始终有效:

    void *v = malloc(10);
    size_t s = (size_t) v;
    

    因此,在C99中,标准引入了 intptr_t uintptr_t 类型,这些类型是有符号和无符号的类型,保证能够保存指针:

    uintptr_t p = (size_t) v;
    

    那么使用的区别是什么呢 西泽特 尤因普特里特 ?两者都是无符号的,并且都应该能够保存任何指针类型,因此它们在功能上似乎是相同的。有什么真正令人信服的理由可以使用吗 尤因普特里特 (或者更好的是, void * )而不是 西泽特 除了清晰?在不透明结构中,字段只由内部函数处理,有没有理由不这样做?

    出于同样的原因, ptrdiff_t 是一个有符号的类型,能够保存指针差异,因此能够保存大多数指针,那么它与 因特特里特 ?

    难道所有这些类型基本上都是为同一个函数提供不同版本的服务吗?如果不是,为什么?我不能用其中一个做什么,而不能用另一个做什么?如果是这样,为什么C99在语言中添加了两种基本上多余的类型?

    我愿意忽略函数指针,因为它们不适用于当前的问题,但请随意提及它们,因为我有一种潜移默化的怀疑,它们将是“正确”答案的核心。

    7 回复  |  直到 6 年前
        1
  •  221
  •   Evan Carroll    6 年前

    size_t 可以保存任何数组索引的类型。这意味着, 从逻辑上讲,尺寸应该能够 保留任何指针类型

    不一定!回到16位分段体系结构的时代,例如:一个数组可能仅限于一个段(所以16位 西泽特 可以),但可以有多个段(因此32位 intptr_t 需要类型来选择段以及其中的偏移量)。我知道这些东西在这些统一地址的非分段体系结构中听起来很奇怪,但是这个标准必须满足比“2009年的正常情况”更广泛的多样性,你知道的!-)

        2
  •  85
  •   paxdiablo    6 年前

    关于你的陈述:

    “C标准保证 size_t 可以保存任何数组索引的类型。这意味着,逻辑上, 西泽特 应该能够保存任何指针类型。“

    这实际上是一个谬论(错误推理导致的误解) (a) .你可以 认为 后者来自前者,但事实并非如此。

    指针和数组索引是 同样的事情。设想一个一致的实现,将数组限制为65536个元素,但允许指针将任何值寻址到大量的128位地址空间,这是很合理的。

    C99规定a的上限 西泽特 变量定义为 SIZE_MAX 这可以低至65535(见c99 tr3,7.18.3,在c11中不变)。如果指针在现代系统中被限制在这个范围内,那么指针将相当有限。

    在实践中,您可能会发现您的假设是成立的,但这并不是因为标准保证了这一点。因为事实上 保证它。


    (a) 这是 某种形式的人身攻击,顺便说一下,为什么你的陈述在批判性思维的背景下是错误的。例如,以下推理也是无效的:

    所有的小狗都很可爱。这东西很可爱。所以这东西一定是小狗。

    小狗的可爱与否与此无关,我所说的只是这两个事实并不能得出结论,因为前两句话允许可爱的事物存在 小狗。

    这类似于你的第一个陈述,不一定要求第二个陈述。

        3
  •  34
  •   unwind    7 年前

    我将让所有其他的答案在分段限制的推理、奇异的体系结构等方面代表自己。

    不是很简单吗 姓名差异 有足够的理由为正确的事情使用正确的类型吗?

    如果要储存尺寸,请使用 size_t . 如果要存储指针,请使用 intptr_t . 一个阅读你的代码的人会立刻知道“啊哈,这是一个东西的大小,可能是以字节为单位的”,还有“哦,这是一个指针值,出于某种原因被存储为一个整数”。

    否则,你只需使用 unsigned long (或者,在这些现代, unsigned long long )为了一切。大小不是全部,类型名带有含义,这是有用的,因为它有助于描述程序。

        4
  •  13
  •   Michael Burr    15 年前

    最大数组的大小可能小于指针。想想分段的架构——指针可以是32位,但是一个段只能寻址64kb(例如旧的实模式8086架构)。

    虽然这些在台式机中不再普遍使用,但C标准旨在支持更小的、专门化的体系结构。例如,仍有一些嵌入式系统是用8位或16位CPU开发的。

        5
  •  5
  •   dreamlax    15 年前

    我可以想象(这适用于所有类型名),它更好地用代码表达您的意图。

    例如,即使 unsigned short wchar_t 在窗户上的尺寸相同吗(我想),用 瓦查特 而不是 无符号短整型 显示了您将使用它来存储宽字符,而不仅仅是一些任意数字的意图。

        6
  •  3
  •   DigitalRoss    15 年前

    回顾过去和过去,我记得各种奇怪的架构分散在风景中,我很确定他们试图包装所有现有的系统,并提供所有可能的未来系统。

    当然,事情解决的方式,我们到目前为止还不需要这么多的类型。

    但即使在LP64(一个相当常见的范例)中,我们也需要系统调用接口的大小和ssize。我们可以想象一个更受约束的遗留系统或未来系统,使用一个完整的64位类型是昂贵的,它们可能希望在大于4GB的I/O操作上投入资金,但仍然有64位指针。

    我想你必须想一想:什么可能被开发出来,什么可能在未来出现。(可能是128位分布式系统互联网范围指针,但在系统调用中不超过64位,甚至可能是“遗留”32位限制。:-)旧系统可能会获得新的C编译器的映像…

    另外,看看当时的情况。除了Zillion 286实模式内存模型外,CDC 60位字/18位指针主机呢?克雷系列怎么样?别介意普通的ILP64,LP64,LLP64。(我一直认为微软是以llp64为借口,应该是p64。)我可以想象,一个委员会试图覆盖所有的基础……

        7
  •  -8
  •   Chris Becke    13 年前
    int main(){
      int a[4]={0,1,5,3};
      int a0 = a[0];
      int a1 = *(a+1);
      int a2 = *(2+a);
      int a3 = 3[a];
      return a2;
    }
    

    这意味着intptr必须总是用大小来代替,反之亦然。