2012-04-29 11 views
14

To jest mój main.cwskaźnik o * argv []

...... 
int main(int argc, char **argv) 
{ 
    init_arg(&argc, &argv); 
    ...... 
} 

To jest mój init_arg.c

...... 
void init_arg(int *argc, char ***argv) 
{ 
    printf("%s\n", *argv[1]); 
    ...... 
} 

I kompilator go bez błędu i ostrzeżenia.

go uruchomić:

./a.out include

ona dostać wina Segmentacja

Kiedy debugować go, znalazłem krok printf("%s\n", *argv[1]);

się źle, to pokazać:

print *argv[1]

Cannot access memory at address 0x300402bfd

Chcę wiedzieć, Jak drukować argv[1] w init_arg() funkcji.

+10

+1 dla pierwszego debugowania i uwzględnienia go w poście! – jedwards

+0

W GDB, gdy twój kod się zawiesza, uruchom polecenie bt, aby zobaczyć ślad stosu prowadzący do awarii. Przeczytaj http://crasseux.com/books/ctutorial/argc-and-argv.html na przykład kod programu C, który obsługuje argumenty programu. –

+0

tutaj jest fragment z przykładami [http://pastebin.com/SVAZjsXA](http://pastebin.com/SVAZjsXA) – dschulz

Odpowiedz

19

Musisz dodać parę nawiasów wokół (* argv), aby zmienić kolejność oceny. Sposób, w jaki go obecnie posiadasz, [1] jest oceniany jako pierwszy, co daje niepoprawny wskaźnik, który następnie zostaje odrzucony, powodując niezdefiniowane zachowanie.

printf("%s\n", (*argv)[1]); 
+1

Lub, równoważnie, można użyć 'argv [0] [1]' (tak samo długo, aby typ, ale być może nieco bardziej czytelny). – torek

+7

@torek Nie używałbym 'argv [0]' zamiast '(* argv)', ponieważ przekazywany jest wskaźnik "skalarny" (tj. Wskaźnik do pojedynczej tablicy), a nie tablica wskaźników do tablic. Myślę, że składnia '(* argv) 'podkreśla pogląd, że patrzymy na wskaźnik do skalaru. – dasblinkenlight

+0

podobno należysz do grupy ludzi, którzy lubią utrzymywać rozróżnienie, że C spada. Sympatyzuje!Na początku lat 80. miałem kolegę, który lubił mieszać wskaźnik i notację tablicową przez cały czas w zależności od tego, co było wygodne. W szczególności robił takie rzeczy jak: 'time_t now [1]; już czas); ... 'zamiast' time_t now; time (&now); ... '. :-) – torek

13

Argv jest już wskaźnikiem. Wystarczy przekazać go tak:

init_arg(&argc, argv); 

I init_arg powinna wyglądać następująco:

void init_arg(int *argc, char **argv) { 
    printf("%s\n", argv[1]); 
} 
+5

Ta odpowiedź jest poprawna, ale mógł też po prostu przekazać 'argc' zamiast' & argc'. Prawdopodobnie punktem do przekazania zarówno '& argc' i' & argv' jest zezwolenie 'init_arg' na ich modyfikację. – torek

+0

Możesz modyfikować oba w ten sposób. – alf

2

jestem przy założeniu, że powodem przechodząc &argc i &argv na pierwszym miejscu jest tak, że można je aktualizować wewnątrz init_arg. Oto jak ja wolę pisać takie funkcje, ogólnie:

/* 
* init_arg: do something useful with argc and argv, and update argc and argv 
* before returning so that the caller can do something else useful that's 
* not shared with all the other callers of init_arg(). 
* (this comment of course needs updating to describe the useful things) 
*/ 
void init_arg(int *argc0, char ***argv0) { 
    int argc = *argc0; 
    char **argv = *argv0; 
    ... all the operative code goes here, and then ... 
    *argc0 = argc; 
    *argv0 = argv; 
} 

Oczywiście oznacza to, że nie musi robić wczesne return s wewnątrz init_arg, więc istnieją pewne kompromisy, ale na pewno jest o wiele łatwiejsze do pracy z ten sam regularny stary argc i argv wewnątrz init_arg.

+1

Po prostu użyj goto, jeśli przegapisz wczesny powrót :) – hugomg

Powiązane problemy