考虑以下 C 代码:
for (data_object_t *first = get_first(dev),
*last = first + get_num_of_data_objects(dev) - 1,
*curr = first;
curr <= last;
curr++) {
// process *curr
}
Run Code Online (Sandbox Code Playgroud)
假设get_first()返回一个指向位于某个大数组中的对象的指针data_object_t,并且get_num_of_data_objects()永远不会返回会导致越界访问的值。
get_num_of_data_objects()我的问题具体是关于返回 0 的情况。
在这种情况下,lastwill 是first - 1,所以我希望简单地跳过循环(因为curr <= last从一开始就评估为 false ),但困扰我的是有可能last指向数组开头之前
,这让我想知道 - 即使它没有被取消引用:
这是一个不好的做法吗?
这里是否存在未定义行为的可能性?
如果first指向数组的开头,first - 1则尝试创建指向数组开头之前的指针。在这种情况下, 的行为first - 1是未定义的。
C 标准第 6.5.6p8 节详细说明了有关指针加法和减法的规则:
\n\n\n当整数类型的表达式与指针相加或相减时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向距原始元素的元素偏移量,使得结果数组元素和原始数组元素的下标之差等于整数表达式。\n换句话说,如果表达式 P 指向数组对象的第 i 个元素,则表达式 (P)+N(相当于 N+(P))和 (P)-N\n(其中 N 的值 n) 分别指向数组对象的第 i+n 个和\ni\xe2\x88\x92n 个元素(前提是它们存在)。此外,如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象最后一个元素的最后一个元素,并且如果表达式 Q 指向数组对象最后一个元素的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素。 array\nobject,表达式 (Q)-1 指向 array\nobject 的最后一个元素。如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则求值不会产生溢出;否则,\n行为是未定义的。如果结果指向数组对象的最后一个元素,则不得将其用作所计算的一元运算符的操作数。
\n
这些规则不允许在数组开头之前创建指针。
\n然而,它们允许的是拥有一个指向数组末尾之后的一个元素的指针(尽管它不能被取消引用)。因此,您可以使用它来修改循环,如下所示:
\nfor (data_object_t *first = get_first(dev),\n *last = first + get_num_of_data_objects(dev),\n *curr = first;\n curr < last;\n curr++) {\n // process *curr\n }\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
124 次 |
| 最近记录: |