C 使用FOR循环时出现分段错误,但在指针数组的qsort实现中使用WHILE时出现分段错误
我目前开始学习C编程,我的长期目标是自学逆向工程,我正在学习丹尼斯·M·里奇的优秀著作。尽管这本书写于90年代,但我还是选择了这本书,因为作者在书中的解释和例子都非常仔细。 无论如何,我在玩作者在5.6节中描述的快速排序算法,并试图通过回忆重写它,但由于我试图用gdb调试的分段错误而遇到了问题。代码是:C 使用FOR循环时出现分段错误,但在指针数组的qsort实现中使用WHILE时出现分段错误,c,for-loop,segmentation-fault,qsort,kernighan-and-ritchie,C,For Loop,Segmentation Fault,Qsort,Kernighan And Ritchie,我目前开始学习C编程,我的长期目标是自学逆向工程,我正在学习丹尼斯·M·里奇的优秀著作。尽管这本书写于90年代,但我还是选择了这本书,因为作者在书中的解释和例子都非常仔细。 无论如何,我在玩作者在5.6节中描述的快速排序算法,并试图通过回忆重写它,但由于我试图用gdb调试的分段错误而遇到了问题。代码是: #include <stdio.h> #define MAX 10000 void sort(int **, int, int); int main(){ int tab
#include <stdio.h>
#define MAX 10000
void sort(int **, int, int);
int main(){
int tab[MAX]={18,7,43,72,2365,743,234,3215,13,456}, i;
int *ptrtab[MAX];
for (i=0; i<MAX && tab[i]>0; i++){
ptrtab[i]=&tab[i];
}
sort(ptrtab, 0, i-1);
for (;i>0;i--) printf ("%d\n",*ptrtab[i]);
return 0;
}
void sort(int **ptrtab,int gauche,int droite){
int i, dernier;
void echanger(int **, int, int);
if (gauche>=droite) return;
dernier=gauche;
for (i=gauche+1; i<=droite; i++){
if (*ptrtab[i]< *ptrtab[gauche])
echanger(ptrtab, ++dernier, i);
}
echanger(ptrtab, gauche, dernier);
sort(ptrtab,dernier+1,droite);
sort(ptrtab,gauche, dernier);
}
void echanger(int **ptrtab,int a,int b){
int *temp=ptrtab[a];
ptrtab[a]=ptrtab[b];
ptrtab[b]=temp;
}
这个代码现在可以工作了。
我知道我的代码中肯定有很多错误,因为我只是一个初学者,但我无法理解为什么从for
更改为,而循环产生了不同。。。
注意,我在ubuntu 16.04上使用GCC
谢谢大家的关注,很抱歉说得太多了。
亲切问候,,
美国。您的while循环实际上与for循环不同。while循环在使用它之前递减i;for循环没有。您的while循环实际上与for循环不同。while循环在使用它之前递减i;for循环不在以下位置。
for (;i>0;i--) printf ("%d\n",*ptrtab[i]);
循环从上一个循环的最后一个值i
开始,在那里它到达数组的末尾(因此i
将是MAX
),或者在它为零的点上索引tab
在第一种情况下,ptrtab[MAX]
将被索引,这是无效的;在第二种情况下,将使用未初始化的ptrtab
条目,它是一个自动变量,将具有随机值(指向随机内存位置,这可能是无效的(未定义的行为)。
for (;i>0;i--) printf ("%d\n",*ptrtab[i]);
循环从上一个循环的最后一个值i
开始,在那里它到达数组的末尾(因此i
将是MAX
),或者在它为零的点上索引tab
在第一种情况下,ptrtab[MAX]
将被索引,这是无效的;在第二种情况下,将使用未初始化的ptrtab
条目,它是一个自动变量,将具有随机值(指向随机内存位置,这可能是无效的(未定义的行为).这本书不教现代和标准C。@Olaf谢谢你的评论。你知道一些这样做的电子书或教程吗?标准是一本好书。但是在某个地方有一个书单。这本书不教现代和标准C。@Olaf谢谢你的评论。你知道一些这样做的电子书或教程吗?标准是这本书读得不错。但是在某个地方有一个书单。将sentinel添加到选项卡是一种方法。另一种方法是避免完全定义MAX
(只需编写tab[]={…}
),而不必为ptrtab数组操心(只需编写tab+i
,无论您在哪里编写ptrtab[i]
),并使用进行迭代(int*start=tab;start
@williampersell:sentinel已经实现。第一个循环仅在..&&tab[i]时运行>0
@jarmod:没有初始值设定项的数组中的剩余元素不是隐式初始化为0吗?@Gerhardh是的,我相信你是正确的,我的错误。全局作用域数组显然已归零,但看起来像是自动的,初始值设定项少于数组的宽度(例如int arr[10]={1,2,3})也被初始化为零。已经删除了我答案中的这一部分,谢谢。@jarmod谢谢你的回答,我选择它是因为你先回答了,而且回答得很简洁明了:)将哨兵添加到选项卡是一种方法。另一种方法是避免完全定义MAX
(只需编写tab[]={…}
),不必为ptrtab数组操心(只要写tab+i
,只要写ptrtab[i]
),并用迭代(int*start=tab;start
@williampersell:sentinel已经实现。第一个循环只在..&&tab[i]时运行>0
@jarmod:没有初始值设定项的数组中的剩余元素不是隐式初始化为0吗?@Gerhardh是的,我相信你是正确的,我的错误。全局作用域数组显然已归零,但看起来像是自动的,初始值设定项少于数组的宽度(例如int arr[10]={1,2,3})也被初始化为零。已经删除了我答案的这一部分,谢谢。@jarmod谢谢你的回答,我选择它是因为你先回答了,而且它很简洁,切中要害:)可能,但更可能的是,I
开始于tab[I]>0
不再为真和ptrtab[I]
没有初始化。@PaulOgilvie感谢您的回答。使用printf(“%d\n”、*ptrtab[i-1])确实解决了这个问题!也许吧,但更可能的是,i
开始于tab[i]>0
不再正确且ptrtab[i]
没有初始化。@PaulOgilvie感谢您的回答。使用printf(“%d\n”,*ptrtab[i-1])确实解决了这个问题!