为什么不一样呢?

时间:2021-06-02 20:14:13
写了个快排,结果一不小心写错了,错误出在第60行附近,有注释说明(代码见最下)。

一开始没发现这个错,就用gcc编译运行,输出结果是有问题的:
1 2 4 5 6 7 8 9 10 11 12 4202196

我又用vs2005编译运行,输出结果是正确的:
1 2 3 4 5 6 7 8 9 10 11 12

调试了半天才知道是自己写错了,但是我对两个编译器的不同运行效果很是好奇:
经过gdb调试我知道了用gcc时,由于我的失误使得a[-1]覆盖了a[7]的值,所以出此效果。

在vs2005中按道理应该会出相同的问题,但我反复运行了好几次,都得到1到12的顺序输出,总不能说每次都是巧合吧(被覆盖者与覆盖者值相同)。而且我输出了a[-1]的值,跟a[7]是不一样的。

我对这个情况非常不理解,希望大家帮忙解答下。

顺便说一句,我本想在vs2005中跟踪调试,但点了调试按钮后弹出个对话框说:无法找到“sort.exe的”调试信息,或者调试信息不匹配。未使用调试信息生成二进制文件。要继续调试吗?我选“是”或“不是”都会退出调试。不知是怎么回事,我的vs2005有的程序能调试,有的就会出这个问题,问一下有没有人知道怎么解决。


#include <stdio.h>

typedef enum
{
FROMLEFT, // 自左向右
FROMRIGHT // 自右向左

} DIRECTION;

// 进行一趟快排
void qsort(int arr[], int begin, int end)
{
// 如果不用再排序了
if(begin == end)
{
return;
}

int pivot = arr[begin]; // 枢轴

// 进行一趟排序
int left = begin; // 左侧工作指针
int right = end - 1; // 右侧工作指针
DIRECTION direction = FROMRIGHT; // 当前位置

while(left != right)
{
if(FROMLEFT == direction) // 如果目前自左向右处理
{
if(arr[left] > pivot) // 绕枢轴旋转
{
// 交换
int temp = arr[right];
arr[right] = arr[left];
arr[left] = temp;

// 移动指针
--right;

// 当前工作指针换到对侧
direction = FROMRIGHT;

// 直接进入下一轮
continue;
}

// 移动指针
++left;
}
else // 如果目前从右往左处理
{
if(arr[right] < pivot) // 绕枢轴旋转
{
// 交换
int temp = arr[right];
arr[right] = arr[left];
arr[left] = temp;

// 移动指针
--left; //应为 ++left;

// 当前工作指针换到对侧
direction = FROMLEFT;

// 直接进入下一轮
continue;
}

// 移动指针
--right;
}
} // while(current != mid)

// 对左半段进行同样处理
qsort(arr, begin, left);

// 对右半段进行同样处理
qsort(arr, left + 1, end);

}

// 快速排序
void QuickSort(int arr[], int length)
{
qsort(arr, 0, length);
}

#define SIZE 12

int main()
{
int a[SIZE] = {7, 4, 6, 8, 9, 5, 2, 3, 10, 1, 12, 11}; //(1)
//int a[SIZE] = {7, 4, 1, 6, 8, 9, 5, 2, 10, 12, 11, 3}; //(2)
//int a[SIZE] = {12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; //(4)
//int a[SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; //(3)
int i;

QuickSort(a, SIZE);

for(i = 0; i < SIZE; ++i)
{
printf("%d ", a[i]);
}
return 0;
}

5 个解决方案

#1


这不是C89的,vc里面只有当c++处理了,
另外调试的时候没问题啊。

#2


怎么写的这么复杂呢。给你个简单的吧。
void quickSort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}



void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;

l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);

#3


由于--left,在运行过程left会变为-1。在vs2005中,arr[-1]的内容是编译器插入的初值0xcccccccc,这个值正好不影响程序给出正确的排序。但在GCC中,arr[-1]是个随机值,在LZ程序运行时,它是4202196,所以最终输出1 2 4 5 6 7 8 9 10 11 12 4202196。

可以在vs2005中模拟GCC的运行环境状况,即插入以下语句:
    int i;
    a[-1]=4202196; //插入
    QuickSort(a, SIZE);
这样在vs2005中也将输出1 2 4 5 6 7 8 9 10 11 12 4202196。

#4


引用 3 楼 logiciel 的回复:
由于--left,在运行过程left会变为-1。在vs2005中,arr[-1]的内容是编译器插入的初值0xcccccccc,这个值正好不影响程序给出正确的排序。但在GCC中,arr[-1]是个随机值,在LZ程序运行时,它是4202196,所以最终输出1 2 4 5 6 7 8 9 10 11 12 4202196。

可以在vs2005中模拟GCC的运行环境状况,即插入以下语句:
  in……

顶这个

#5


菜鸟学习了。。。。。。。。。

#1


这不是C89的,vc里面只有当c++处理了,
另外调试的时候没问题啊。

#2


怎么写的这么复杂呢。给你个简单的吧。
void quickSort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}



void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;

l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);

#3


由于--left,在运行过程left会变为-1。在vs2005中,arr[-1]的内容是编译器插入的初值0xcccccccc,这个值正好不影响程序给出正确的排序。但在GCC中,arr[-1]是个随机值,在LZ程序运行时,它是4202196,所以最终输出1 2 4 5 6 7 8 9 10 11 12 4202196。

可以在vs2005中模拟GCC的运行环境状况,即插入以下语句:
    int i;
    a[-1]=4202196; //插入
    QuickSort(a, SIZE);
这样在vs2005中也将输出1 2 4 5 6 7 8 9 10 11 12 4202196。

#4


引用 3 楼 logiciel 的回复:
由于--left,在运行过程left会变为-1。在vs2005中,arr[-1]的内容是编译器插入的初值0xcccccccc,这个值正好不影响程序给出正确的排序。但在GCC中,arr[-1]是个随机值,在LZ程序运行时,它是4202196,所以最终输出1 2 4 5 6 7 8 9 10 11 12 4202196。

可以在vs2005中模拟GCC的运行环境状况,即插入以下语句:
  in……

顶这个

#5


菜鸟学习了。。。。。。。。。