比较 ptrdiff_t 与 size_t

Comparing ptrdiff_t with size_t

我对以下简单比较有疑问:

#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:

If both of the operands have arithmetic type, the usual arithmetic conversions are performed.

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

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

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

QUESTION:假设ptrdiff_t的转换排名严格大于size_t,而ptrdiff_t不能代表所有的值size_t。如果 ptrdiff_t 没有相应的无符号整数类型,则在 ptrdiff_tsize_t 之间执行比较时会发生什么情况。甚至允许这样的实现吗?

如果ptrdiff_t的秩大于size_t并且可以表示size_t的所有正值。 limit - buf <= sizeof buf 没有问题。比较完成为 ptrdiff_t.

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

J.2 Undefined behavior
The behavior is undefined in the following circumstances:
...
The result of subtracting two pointers is not representable in an object of type ptrdiff_t (6.5.6).


Is such an implementation even allowed? (conversion rank of ptrdiff_t is strictly greater than of size_t and ptrdiff_t cannot represent all the values of size_t)

可以允许 ptrdiff_t 作为 longsize_t 作为 unsigned。都是 32 位的。但也许不明智。


注意:C17 § 7.19 4 有

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

并不是说这在这里很适用 - 只是一个注释。