为什么这个快速排序实现会给出正确的输出而不是垃圾值?

Why this quicksort implementation gives correct output instead of garbage value?

提问人:SnowPuff 提问时间:6/5/2023 最后编辑:SnowPuff 更新时间:6/5/2023 访问量:73

问:

在快速排序的这段代码中,如果输入数组正在递减,例如 5 4 3 2 1 ,变量 i 继续递增而不检查并超出数组边界。这不应该产生分割错误吗?正如回复中指出的那样,即使它没有给出分段错误,为什么它不将 arr[j] 与 arr[i](其中 i 越界)中的垃圾值交换?

int HoarePartition(int a[],int l,int r)
{
    int p,i,j,temp;
    p=a[l],i=l,j=r+1;
    do
    {
        do
        {
            i++;
        }while(a[i]<p);
        do
        {
            j--;
        }while(a[j]>p);
        temp=a[i];
        a[i]=a[j];
        a[j]=temp;
    }while(i<j);
    temp=a[i];
    a[i]=a[j];
    a[j]=temp;
    temp=a[l];
    a[l]=a[j];
    a[j]=temp;
    return j;
}

这与快速排序功能一起为输入数组 5、4、3、2、1 或类似的递减数组提供了正确的排序数组。

C 分段-故障 快速排序 索引OutofboundsException

评论

3赞 Weather Vane 6/5/2023
不需要不正确的代码来给出 seg 错误。如果它破坏了某些东西,它就会。
1赞 Some programmer dude 6/5/2023
超出数组或分配的内存的范围会导致未定义的行为
0赞 SnowPuff 6/5/2023
但是为什么它能给出正确的输出呢?当我超出数组限制时,它不会将数组元素与一些垃圾值交换吗?
1赞 Eric Postpischil 6/5/2023
@WeatherVane:C 标准中没有要求“不正确”的代码会导致分段错误。在各种操作系统中,根据操作系统的规范,“不正确”的代码会给出分段错误。此类故障对于安全和其他目的至关重要。
0赞 SnowPuff 6/5/2023
@EricPostpischil 但是为什么它会给出正确的输出呢?为什么它不会越界并用一些垃圾值交换数组元素?

答:

4赞 Eric Postpischil 6/5/2023 #1

这不应该产生分割错误吗?

不。未指定分段错误来捕获超出进程中单个数组或其他对象边界的错误。在具有它们的操作系统上,指定它们以捕获使用不正确的进程权限访问内存的错误,例如尝试在进程有权读取的内存边界之外读取,尝试在进程有权写入的内存边界之外写入,或尝试在进程有权执行的内存边界之外执行指令。

当一个进程有两个数组 和 时,使用 在 into 之外扩展的 进行读取不会产生分段错误,因为该进程具有读取 的权限。当进程在为其堆栈分配(和映射)的内存中有一个数组时,使用延伸到其堆栈空间外部但仍在其堆栈空间内的 进行读取不会产生分段错误。aba[i]iabbaa[i]ia

为什么代码会给出正确的输出?

在交换后和循环内部,例程立即将它们交换回来,反转更改。这是因为,once is outing, is false,因为 start at 和 is 递减,所以我们知道它在 bounds 内,因此小于 。因此,循环 with 终止,紧随其后的代码 swap 和 被执行。a[i]a[j]doii<jjr+1iwhile(i<j)a[i]a[j]

因此,只要没有发生段故障,与阵列外部元素的任何交换都会立即被撤消,并且不会产生持久影响。

评论

0赞 SnowPuff 6/5/2023
在哪里可以找到并了解有关这种反向出站交换行为的更多信息?谢谢你的回答
0赞 Andrew Henle 6/5/2023
@SnowPuff在哪里可以找到并了解有关这种反向出站交换行为的更多信息? 您的代码正在执行此操作。