【问题标题】:Comparing ptrdiff_t with size_t比较 ptrdiff_t 和 size_t
【发布时间】:2019-12-24 04:23:45
【问题描述】:

我有一个关于以下简单比较的问题:

#define BUF_SIZE //maybe large

static char buf[BUF_SIZE];

static char *limit; // some pointer to an element of buf array

void foo(){
    if(limit - buf <= sizeof buf){  //<---- This comparison
        //...
    }
    //...
}

在这里,我们比较了有符号的ptrdiff_t(左侧)和未签名的size_t(右侧)。该标准提供以下解释

6.5.8/3:

如果两个操作数都有算术类型,通常的算术 执行转换。

6.3.1.8/1 给了我们3种可能性:

否则,如果无符号整数类型的操作数有秩 大于或等于另一个操作数的类型的等级,则 带符号整数类型的操作数转换为 无符号整数类型的操作数。

否则,如果带符号整数类型的操作数的类型可以 用无符号表示操作数类型的所有值 整数类型,然后转换无符号整数类型的操作数 为有符号整数类型的操作数的类型。

否则,两个操作数都转换为无符号整数类型 对应带符号整数类型的操作数的类型。

我们不知道ptrdiff_tsize_t 的转化排名。此外,ptrdiff_t 通常没有对应的无符号类型(不像intptr_tuintptr_t)。

问题:假设ptrdiff_t的转化排名严格大于size_tptrdiff_t不能代表size_t的所有值。如果ptrdiff_t 没有对应的无符号整数类型,在ptrdiff_tsize_t 之间执行比较会发生什么。这样的实现是否允许?

【问题讨论】:

  • 为什么6.2.5/6不适用?它明确表示必须有一个无符号类型对应于ptrdiff_t。我们不知道它的名字是什么,但它一定存在。
  • @rici 子句使用关键字unsigned 定义了相应的无符号类型。但根据 6.7.2/2 unsigned ptrdiff_t 不是有效的类型说明符。
  • St.Antario: 没有。如果ptrdiff_t是一个类型别名,那么对应的无符号类型就是ptrdiff_t是一个别名的类型对应的无符号类型。类型别名不是不同的类型;它们是同一类型的不同名称。这就是为什么我说我们不知道对应的无符号类型的名称。我们不知道如何声明它并不意味着它不存在。
  • 事实上,ptrdiff_t 可能是扩展整数类型的别名,其名称位于为实现保留的命名空间部分中。但它仍然会有对应的无符号类型。
  • size_tptrdiff_t 的各种特质在过去二十多年的时间里被广泛讨论。在这里,在邮件列表、博客上,最重要的是在委员会提交的文件中。我认为另一场讨论不太可能揭示任何新内容。如果您对扩展整数类型的实现感兴趣,您当然可以找到它们。我不知道是否对此类类型的基本名称达成共识;我的感觉是类型别名很常见。

标签: c integer language-lawyer conversion-rank


【解决方案1】:

如果ptrdiff_t 的等级高于size_t,并且可以表示size_t 的所有正值。 limit - buf &lt;= sizeof buf 没有问题。比较以ptrdiff_t 完成。

否则ptrdiff_t 可能不代表size_t 的所有正值,然后减法 limit - buf 可能是UB per below,所以比较是moot

J.2 未定义的行为
在以下情况下行为未定义:
...
两个指针相减的结果无法在 ptrdiff_t (6.5.6) 类型的对象中表示。


甚至允许这样的实现吗? (ptrdiff_t的转化等级严格大于size_tptrdiff_t不能代表size_t的所有值)

Yes 可以被允许为ptrdiff_tlongsize_tunsigned。都是 32 位的。但也许并不明智。


注意:C17 § 7.19 4 有

推荐做法
用于size_tptrdiff_t 的类型的整数转换等级不应大于signed long int 的整数转换等级,除非实现支持足够大的对象以使其成为必要。

这并不适用于这里 - 只是一个注释。

【讨论】:

  • 可以允许 ptrdiff_t 和 size_t 一样长,而 size_t 可以是无符号的。 在这种情况下,ptrdiff_t 有一个对应的无符号整数类型。该标准没有指定ptrdiff_t 应该是typedef。如果ptrdiff_tlong 具有相同的表示但没有相应的无符号整数类型,我们在进行此类比较时会得到UB吗?
  • @St.Antario 这个答案不依赖于 ptrdiff_t 具有相应的 unsigned 类型。在第一种情况下,limit - buf &lt;= sizeof buf 全部作为ptrdiff_t 完成。在下一种情况下,limit - buf 是带有大 limit 的 UB。
猜你喜欢
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
  • 2015-07-28
  • 2018-05-08
  • 2014-08-15
相关资源
最近更新 更多