0

我问自己是否可以安全地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]将传递一个数组长度,但程序仍然可以工作。

4

5 回答 5

1

No, accessing elements out of bounds is Undefined Behavior.

Your program may "seem" to work, but you cannot expect anything out of it. It could work on your machine, and crash on another one. Or it could work on all machines now, but not tomorrow. You should check if the index is out-of-bounds before using the subscript operator.

You may consider changing your cycle so that it never accesses out-of-bounds elements:

for (int i = 0; i < n - 1; i++)
//                  ^^^^^

Then, you would have to take care of the last element in the array separately, as a special case.

于 2013-03-17T14:38:16.473 回答
0

That's not correct, when i reaches its last value (n-1) you check the value of a nonexistent element (the C standard allows you to have a pointer to one-after-last element, but not to dereference it).

You can fix your code like this:

 if((a[i] == el ) && ((i == n-1) || (a[i+1] != el)))
于 2013-03-17T14:39:26.273 回答
0

If n is the last element in the array, then i + 1 is safe in this case. If n is the number of elements in the array, i + 1 may appear to work most of the time, but it is not safe.

In that case, you're accessing an element outside the bounds of the array, which may do anything from giving you incorrect results to crashing your program. Most of the time it will appear to work, though, making the problem very hard to debug when it happens.

于 2013-03-17T14:40:16.697 回答
0

我不清楚你在问什么。即使数组访问成本高昂,访问两者a[i]a[i+1]保持 O(N) 复杂度。您不能做的是添加基于的复杂性i(例如从 0 到 的附加循环i),或修改i(例如根据某些条件递减它)。

正如其他人已经指出的那样,问题在于最后一个元素与一个不存在的数据进行比较:要么你会得到一个错误和可能的崩溃,要么程序看起来正在运行——实际上大部分时间都在运行- 直到那个未知且可能是随机的最后一个项目将触发比较并产生意外结果的时间。

您应该检查数组大小是否至少为 1(无论如何这应该是一种特殊情况,不能对单个元素运行比较!),然后只循环到n-1. 或者您可以将先前的值保存在临时变量中;根据平台的不同,这将是一个(可能快得多的)寄存器,或者是一个(可能慢得多的)堆栈位置。在大多数情况下,我只是陈述我与下一个元素进行比较的意图,就像您所做的那样,然后让编译器对其进行排序。

于 2013-03-17T14:46:57.307 回答
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.

发生了什么 ?编译器将值 1886221680 写入 a[3] 和 a[4] 如果存在的话。关于在您的机器上运行的程序:阅读关于我的机器概念上的作品。

http://www.codinghorror.com/blog/2007/03/the-works-on-my-machine-certification-program.html

于 2013-03-17T15:10:09.757 回答