这可能不是对原始问题的直接回答,但我强烈建议不要养成这样解析数组的习惯(这就像一个定时炸弹等待在随机时间点爆炸)。
我知道您说过您已经知道 x 是 xs 的成员,但是如果不是(并且由于各种原因可能会意外发生),那么如果幸运的话,您的循环将使您的程序崩溃,否则它将破坏不相关的数据你不走运。
在我看来,通过额外的检查进行防御既不丑也不“hacky”。
如果障碍是看似未知的 xs 长度,则不是。静态数组通过声明或初始化(如您的示例)具有已知长度。在后一种情况下,可以在声明的数组范围内按需计算长度,sizeof(arr) / sizeof(*arr)您甚至可以将其设为可重用宏。
#define ARRLEN(a) (sizeof(a)/sizeof(*(a)))
...
int xs[] = {1,2,3,4,5};
/* way later... */
size_t xslen = ARRLEN(xs);
for (size_t i=0; i < xslen; i++) {
if (xs[i] == 4) {
foo( xs[i] );
break;
};
}
即使数组中不存在 4,这也不会超出 xs。
编辑:
“在声明的数组的范围内”意味着宏(或其直接代码)将不适用于作为函数参数传递的数组。
// This does NOT work, because sizeof(arr) returns the size of an int-pointer
size_t foo( int arr[] ) {
return( sizeof(arr)/sizeof(*arr) );
}
如果您需要函数内部数组的长度,您也可以将它作为参数与数组一起传递(实际上只是指向第一个元素的指针)。
或者,如果性能不是问题,您可以使用sentinel下面解释的方法。
[编辑结束]
另一种方法是用一个sentinel值(您故意认为无效的值)手动标记数组的末尾。例如,对于整数,它可以是 INT_MAX:
#include <limits.h>
...
int xs[] = {1,2,3,4,5, INT_MAX};
for (size_t i=0; xs[i] != INT_MAX; i++) {
if (xs[i] == 4) {
foo( xs[i] );
break;
};
}
哨兵在解析未知长度的动态分配的指针数组时非常常见,哨兵为 NULL。
无论如何,我的主要观点是,与代码美观相比,防止意外缓冲区溢出可能具有更高的优先级:)