【问题标题】:Why is the st_size field in struct stat signed?为什么 struct stat 中的 st_size 字段是签名的?
【发布时间】:2012-08-29 20:12:26
【问题描述】:

st_sizedefined 作为 off_t

off_tdefined 作为一个有符号整数类型

为什么st_size 被定义为有符号类型?可以是负数吗?如果是负数是什么意思?

【问题讨论】:

    标签: c linux unix posix


    【解决方案1】:

    我能想到的最好的理由是避免引入off_t 的无符号版本作为额外类型; POSIX 已经拥有大量具有相似用途的整数类型。

    除此之外,当大小不是一个有意义的概念时,能够在st_size 中存储-1 可能很有用;我不确定是否有任何实现这样做,我找不到 POSIX 对st_size 的内容提出任何要求的地方,除了常规文件和符号链接......

    【讨论】:

    • POSIX 在哪里对常规文件提出了st_size 的要求?
    • POSIX 要求 st_size 反映常规文件的文件实际大小,并要求它反映符号链接的符号链接长度。 stat 记录了对符号链接的要求;那里似乎省略了对常规文件的要求,但sys/stat.h 的文档说对于常规文件,st_size 是文件的大小(以字节为单位)。
    【解决方案2】:

    根据 C 的提升规则,只要没有任何中间计算溢出,组合不同大小的有符号类型的表达式将表现出相同的算术正确方式,而不管所涉及的大小如何。但是,添加无符号类型会使代码的行为更加依赖于整数大小。

    给定:

    int test_size(off_t x, long y, long long z)
    {
      return x-y > z;
    }
    

    如果off_t 未签名,则根据其大小,它可能导致y 得到 提升为unsigned long,并在该类型上执行计算,然后将其提升为signed long long并使用有符号比较与z进行比较,或者可能导致z提升为unsigned long long,其中情况下,整体比较将以无符号方式进行。 off_t 也有可能(尽管不一定)足够小(和/或 long 足够大)以致使用有符号算术减去 y

    可能大到需要至少与int 一样大的数量,即使它们永远不会是负数,通常只有在有理由相信它们不适合特定的情况下才应该用无符号类型表示带符号的类型,但肯定适合其未签名的对应物。这种情况并不常见,但在 16 位系统上存在 size_t(在架构上单个对象不可能超过 64K,但超过 32K 的对象很常见)。这种情况在文件系统接口中似乎不太引人注目(如果 32 位有符号还不够,那么 32 位无符号也可能在很长时间内也不够用)。

    【讨论】:

    • 关于混合类型数学的有趣论述。在这个假设中使用x-y*1LL > z 可能会有所帮助,但仍然存在角落故障。嗯。
    【解决方案3】:

    off_t 定义文件中的偏移量,它可以等于文件的大小,但也可以是负数,例如向后搜索时。

    从偏移量和大小之间的这种关系来看,文件的大小与文件偏移量具有相同的类型。无论如何,文件大小不得为负数。

    【讨论】:

      【解决方案4】:

      我认为 POSIX 中的某些 fseek 函数需要接受负数作为偏移量。

      【讨论】:

        【解决方案5】:

        off_t 用于处理许多函数中的文件偏移量。某些函数使用特殊值 -1(例如,lseek 这样做是为了告诉您发生了错误)。许多其他数据类型在 UNIX 中签名以适应 -1 值(例如 time_t)。

        【讨论】:

        • 注意lseek的参数是一个相对文件位置(偏移量),这是off_t需要签名的主要原因。而且您只能寻求正的绝对文件位置这一事实施加了一个限制,即文件不能大于(有符号)类型off_t 的最大值,因此没有符号的filesize_t 没有任何用处以保持更大值。
        猜你喜欢
        • 2012-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-05
        相关资源
        最近更新 更多