5

我正在通过连续的内存块实现迭代器,并遇到了关于它的一致性使用的问题。我当前的实现(假设我正在遍历chars 数组)。

typedef struct iterator{
    void *next_ptr;
    void *limit; //one past last element pointer
} iterator_t;

void *next(iterator_t *iterator_ptr){
    void *limit = iterator_ptr -> limit;
    void *next_ptr = iterator_ptr -> next_ptr;
    ptrdiff_t diff = limit - next_ptr;
    if(diff <= 0){
        return NULL;
    }
    iterator_ptr -> next_ptr = ((char *) next_ptr) + 1;
    return next_ptr;
}

问题是标准声称6.5.6(p9)

当两个指针相减时,它们都应指向同一个数组对象的元素,或者指向数组对象的最后一个元素

这是真实的。我假设我正在迭代的区域是一个数组。

如果结果在该类型的对象中不可表示,则行为未定义。换句话说,如果表达式分别指向数组对象的i第 -th 和-th 元素,则表达式具有值,前提是该值适合类型为 的对象。j(P)-(Q)i−jptrdiff_t

的限制ptrdiff_t定义为7.20.3(p2)

的限制ptrdiff_t

PTRDIFF_MIN −65535

PTRDIFF_MAX +65535

不能保证用 表示的所有值size_t都应该用 表示ptrdiff_t

所以我们根据限制来判断,我们最多可以一致地减去一个数组的指针65535吗?所以这在我想减去两个指向未知大小数组元素的指针的一般情况下不起作用?

4

2 回答 2

5

来自规范(第 7.20.3 节)

其实现定义的值在幅度(绝对值)上应等于或大于下面给出的相应值

[强调我的]

所以提到的值只是最小值。实施可能有更大的限制。我希望ptrdiff_t是目标平台的字长(即 64 位类型的 64 位系统)。

并注意这size_t无符号整数类型,ptrdiff_t而是有符号整数类型。这意味着并非 a 的所有值size_t都可以由 a 表示ptrdiff_t

于 2019-03-26T16:02:36.753 回答
3

这似乎是 C 标准本身的问题。

正如您所指出的,6.5.6 加法运算符第 9 段部分指出:

当两个指针相减时,都应指向同一个数组对象的元素,或者指向数组对象的最后一个元素;结果是两个数组元素的下标之差。结果的大小由实现定义,其类型(有符号整数类型)ptrdiff_t在标头中定义<stddef.h>如果结果在该类型的对象中不可表示,则行为未定义。换句话说,如果表达式PQ分别指向数组对象的i第 -th 和-th 元素,则表达式具有值适合类型对象的值。...j(P)-(Q)i-j ptrdiff_t

C 标准中似乎不能保证您可以表示 a 中两个指针的差异ptrdiff_t

实际上,这意味着 aptrdiff_t必须大于 a size_t。Asize_t只需覆盖固定位数的幅度。 ptrdiff_t必须涵盖大小和方向。如果sizeof( size_t ) == sizeof( ptrdiff_t ),则不能保证不会调用 6.5.6p9 中的未定义行为。

于 2019-03-26T16:39:33.197 回答