Som*_*ame 5 c language-lawyer ptrdiff-t
我正在通过连续的内存块实现迭代器,并遇到了有关其一致性用法的问题。我当前的实现(假设我正在遍历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;
}
Run Code Online (Sandbox Code Playgroud)
问题在于标准索赔6.5.6(p9):
当减去两个指针时,两个指针均应指向同一数组对象的元素,或者指向数组对象的最后一个元素
这是真的。我假设我要遍历的区域是一个数组。
如果结果无法在该类型的对象中表示,则该行为未定义。换句话说,如果表达式分别指向数组对象的
i-th和j-th元素,则该表达式(P)-(Q)具有值,i?j只要该值适合于type对象ptrdiff_t。
的限制在以下ptrdiff_t位置定义7.20.3(p2):
极限
ptrdiff_t
PTRDIFF_MIN65535英镑
PTRDIFF_MAX+65535
不能保证用表示的所有值size_t都应用表示ptrdiff_t。
因此,根据限制判断,我们最多只能一致地减去仅65535元素数组的指针?因此,在我要减去两个指针的数组的大小未知的一般情况下,这是行不通的吗?
来自规范(第 7.20.3 节)
其实现定义的值应等于或大于下面给出的相应值的幅度(绝对值)
[强调我的]
所以提到的值只是最小值。实施可能有更大的限制。我希望ptrdiff_t是目标平台的字长(即 64 位系统的 64 位类型)。
并注意size_t是无符号整数类型,而ptrdiff_t是有符号整数类型。这意味着并非 a 的所有值size_t都可以用 a 表示ptrdiff_t。
这似乎是C标准本身的问题。
正如您所指出的,6.5.6 加法运算符第 9 段部分指出:
当两个指针相减时,两个指针都应指向同一个数组对象的元素,或者指向数组对象最后一个元素之后的一个;结果是两个数组元素的下标之差。结果的大小是实现定义的,其类型(有符号整数类型)
ptrdiff_t在<stddef.h>标头中定义。如果结果无法用该类型的对象表示,则行为未定义。换句话说,如果表达式P和Q分别指向数组对象的第i-th 和j-th 元素,则表达式(P)-(Q)具有该值i-j,前提是该值适合类型 的对象ptrdiff_t。...
C 标准中似乎无法保证您可以表示 中两个指针的差异ptrdiff_t。
实际上,这意味着 aptrdiff_t必须大于 a size_t。Asize_t只需要以固定位数覆盖幅度。 ptrdiff_t必须涵盖大小和方向。如果sizeof( size_t ) == sizeof( ptrdiff_t ),则不能保证 6.5.6p9 中未定义的行为不会被调用。