我问自己,使用i+1
检查下一个号码是否与当前号码相同是否安全...示例:
int search(int el, int* a, int n) {
if(a == NULL && n<0)
{
return NULL;
}
for(int i=0; i<n; i++)
{
if((a[i] == el )&& (a[i+1] != el)) // here I check next element
{
return i; // if I find it, return a position.
}
}
return -1; // else return -1
}
如果我们有一个长度为4
的数组,那么a[i+1]
将传递一个数组长度,但程序仍然有效。
答案 0 :(得分:1)
不,访问超出范围的元素是未定义的行为。
你的程序可能“似乎”可以工作,但是你不能指望任何东西。它可以在你的机器上工作,并在另一台机器上崩溃。或者它可以在现在的所有机器上运行,但不能在明天运行。在使用下标运算符之前,应检查索引是否超出范围。
您可以考虑更改周期,以便它永远不会访问越界元素:
for (int i = 0; i < n - 1; i++)
// ^^^^^
然后,作为特例,你必须分别处理数组中的最后一个元素。
答案 1 :(得分:0)
这是不正确的,当i
到达其最后一个值(n-1
)时,你检查一个不存在的元素的值(C标准允许你有一个指向一个接一个元素的指针,但不要取消引用它。)
您可以像这样修复代码:
if((a[i] == el ) && ((i == n-1) || (a[i+1] != el)))
答案 2 :(得分:0)
如果n
是数组中的最后一个元素,那么i + 1
在这种情况下是安全的。如果n
是数组中元素的数量,i + 1
似乎在大多数时间都可以正常工作,但不是安全的。
在这种情况下,您正在访问数组范围之外的元素,这可能会导致从错误的结果到崩溃程序。但是,大多数情况下它似乎都会起作用,这使得问题很难在调试时进行调试。
答案 3 :(得分:0)
我不清楚你在问什么。即使数组访问很昂贵,访问a[i]
和a[i+1]
仍然具有O(N)复杂性。你无法做的是增加基于i
的复杂性(例如从0到i
的额外循环),或修改i
(例如)根据某些条件减少它。)
正如其他人已经指出的那样,问题在于将最后一个元素与不存在的数据进行比较:要么出错,要么可能发生崩溃,或者程序出现到正在工作 - 实际上工作大多数 - 直到那个未知的,可能是随机的最后一个项目将触发比较,并产生意外结果的时间。
您应该检查数组大小是否至少为1(无论如何都应该是特殊情况,不能对单个元素进行比较!)然后仅循环到n-1
。或者您可以将先前的值保存在临时变量中;取决于平台,这将是(可能更快)寄存器,或(可能更慢)堆栈位置。在大多数情况下,我只是说明我打算与下一个元素进行比较,就像你一样,让编译器对其进行排序。
答案 4 :(得分:0)
没有
int main(void)
{
char pumpkin[8];
int a[4];
int i, p;
a[0] = 3760;
a[1] = 100001;
a[2] = 595959;
a[3] = 1886221680;
pumpkin[0] = 'p';
pumpkin[1] = 'u';
pumpkin[2] = 'm';
pumpkin[3] = 'p';
for (i = 0; i < 4; i++) {
p = search(a[i], a, 4);
if (p >= 0)
printf("Found it at position %d: %d.\n", p, a[i]);
else
printf("Value not found.\n");
}
return 0;
}
在我的机器上:
$ gcc -std=c11 -o boundserror boundserror.c
$ ./boundserror
Found it at position 0: 3760.
Found it at position 1: 100001.
Found it at position 2: 595959.
Value not found.
发生什么事了?编译器在[3]中写入了值1886221680,如果存在,则编号为[4]。关于在您的机器上工作的程序:阅读有关我的机器概念的工作。
http://www.codinghorror.com/blog/2007/03/the-works-on-my-machine-certification-program.html