0

저는 현재 C 프로그래밍에서 시작하고 있습니다. 장기 목표는 리버스 엔지니어링을 가르치고 있습니다. 데니스 M. 리치 나는 90 년대에 작성된 책 임에도 불구하고이 책을 선택했다. 왜냐하면 저자는 그것을 통해 설명과 예들에 많은 돈을 지불했기 때문이다. 어쨌든 저자는 5.6 절에서 설명한 quicksort 알고리즘을 가지고 놀고 있었고 리콜로 재 작성하려고했지만 gdb로 디버깅하려고했던 세그먼트 화 오류로 인해 문제가 발생했습니다. 코드는했다 :FOR 루프를 사용할 때 세그먼트 오류가 발생합니다. 포인터 배열에 대해 qsort를 구현할 때 WHILE을 사용할 때가 아닙니다.

#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; 
} 

길고도 짧은 이야기, 나는 그것에 휴식을 넣어 분할 오류가 루프의 첫 번째 반복에서 프로그램을 추락하고 printf을 얻지 못한 원인 (for (;i>0;i--) printf ("%d\n",*ptrtab[i]);)의 라인을 확인 후 '사형 당하지 않았다. 그래서 난 그냥 대신 while 루프를 넣어 내 코드에서 줄을 변경 :

#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); 
    while (i>0) 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에서 while 루프로 변경하는 이유가 무엇인지 파악할 수 없습니다. GCC를 사용하고 있습니다. 우분투 16.04.

주의 해 주셔서 감사 드리며 미안합니다. 친절한 답변, S. A.

+0

책은 현대적이고 표준적인 C를 가르쳐주지 않습니다. – Olaf

+0

@Olaf 의견을 보내 주셔서 감사합니다. 일부 전자 책 또는 자습서를 알고 있습니까? –

+0

표준은 좋은 읽을 수 있습니다.하지만 어딘가에 책 목록이 있습니다. – Olaf

답변

4

while 루프는 for 루프와 실제로 다릅니다. while 루프는 을 사용하기 전에 전에 감소합니다. for 루프는 그렇지 않습니다. 지점에서

for (;i>0;i--) printf ("%d\n",*ptrtab[i]); 
루프 중 하나는 어레이의 끝에 도달하기 이전의 루프에서 i의 최종 값으로 시작

은 (따라서 i 될 것이다 MAX) 또는 인덱스 tab :

+0

탭에 센티널을 추가하는 것이 한 가지 방법입니다. 또 다른 방법은'MAX '를 완전히 정의하는 것을 피하는 것입니다 ('tab [] = {...}'). ptrtab 배열에 신경 써라. (단지'tab + i' ev라고 써라. erywhere'ptrtab [i]'라고 쓰고, for (int * start = tab; 시작

+0

@WilliamPursell : 감시 카메라가 이미 구현되었습니다. 첫 번째 루프는'... && tab [i]> 0'만큼 길게 실행됩니다. – Gerhardh

+1

@jarmod : 이니셜 라이저가없는 배열의 나머지 요소가 암시 적으로 0으로 초기화되지 않습니까? – Gerhardh

1

에서 여기서 그것은 0입니다.

첫 번째 경우에는 ptrtab[MAX]이 색인화되며, 두 번째 경우에는 초기화되지 않은 항목 인 ptrtab이 사용됩니다. 두 번째 경우에는 자동 변수 인 임의 값 (임의의 메모리 위치를 나타냄)이 사용됩니다 (정의되지 않은 동작) 가능성이 있습니다.

+0

아마도,'tab' [i]> 0'가 더 이상 TRUE가 아니고'ptrtab [i]'가 아닌 지점에서'i'가 시작될 가능성이 더 큽니다. 초기화 됨. – Gerhardh

+0

@ 게르하르트, 당신 말이 맞아요. 내 대답이 업데이트되었습니다. –

+0

@PaulOgilvie 답변 해 주셔서 감사합니다. printf ("% d \ n", * ptrtab [i-1])를 사용하면 실제로 문제가 해결되었습니다! –