2014-11-30 8 views
7

CODE 1Unterschied zwischen char * argv [] und char ** argv für das zweite Argument main()

#include<stdio.h> 

int main(int argc, char *argv[]) 
{ 
int j; 
printf("%d", argv[1][0]); 
return 0; 
} 

CODE 2

#include<stdio.h> 

int main(int argc, char **argv) 
{ 
int j; 
printf("%d", argv[1][0]); 
return 0; 
} 

CODE CODE 1 und 2 geben beide den gleichen Ausgang. aber Argument 2 der Hauptfunktion in CODE 1 und CODE 2 sind unterschiedlich. Eine Reihe von Zeigern wird oberhalb des Datenabschnitts zum Zeitpunkt der Kompilierung erzeugt. argv ist ein Array von Zeigern. Dann sollten wir das Argument in der Hauptfunktion als Zeiger auf den Zeiger auf das Zeichen deklarieren, d. H. ** argv. Wie ist es korrekt, wie in CODE 1 zu deklarieren?

+6

Zweiter Parameter unterscheidet sich in keiner Weise, was den Compiler betrifft, das heißt, char * argv [] 'ist nur äquivalent zu' char ** argv'. Das ist eher eine Frage des bevorzugten Codierungsstils. –

+0

mögliche Duplikate von [Was sollte main() in C und C++ zurückgeben?] (Http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c) –

Antwort

7

Es ist von grundlegender Bedeutung für c dass char** x und char* x[] gibt zwei Möglichkeiten zum Ausdruck zu bringen die gleiche Sache. Beide deklarieren, dass der Parameter einen Zeiger auf ein Array von Zeigern empfängt. Erinnern Sie sich, dass Sie immer schreiben können:

char *parray[100]; 
char **x; 

x = &parray[0]; 

und dann x identisch verwenden.

+4

Abgesehen von der Verwendung von 'sizeof' –

+0

@EdHeal sicher genug – bmargulies

+0

@EdHeal Bitte unterrichten mehr? –

9

Grundsätzlich bedeutet char * argv [] Array von char-Zeigern, während char ** argv Zeiger auf einen char-Zeiger bedeutet.

In jedem Array ist der Name des Arrays ein Zeiger auf das erste Element des Arrays, dh es enthält die Adresse des ersten Elements.

Also in dem unten angegebenen Code, in Char-Array x, ist x ein Zeiger auf das erste Element, '1', das ein Zeichen ist. Es ist also ein Zeiger auf ein Zeichen.

Und in Array arr, arr ist Zeiger erstes Element, x, die selbst ein Zeiger auf ein Zeichen ist. Also ein Zeiger auf einen anderen Zeiger.

Daher ist x char * und arr ist char **.

Beim Empfangen von etwas in einer Funktion, ist die Grundregel, dass Sie den Typ der Sache, die Sie erhalten, sagen müssen. Entweder sagst du einfach, dass du ein char ** erhalten möchtest, oder du kannst auch char * arr [] sagen.

Im ersten Fall müssen wir nichts Komplexes denken. Wir wissen einfach, wir erhalten ein Array von char *. Wissen wir das nicht? Also, wir bekommen es und benutzen es.

Im zweiten Fall ist es einfach, wie ich oben erklärt habe, dass arr ist ein char **, können Sie dies wie es ist Typ und erhalten es sicher. Jetzt kennt das System den Typ des Materials, das wir erhalten haben, und wir können auf die nächsten Elemente zugreifen, indem wir einfach die Array-Annotation verwenden. Es ist so, wir haben die Startadresse des Arrays erhalten, wir können sicher zu den nächsten Elementen gehen, und da wir wissen, dass es ein Typ ist, wissen wir, was es enthält und wie wir das weiter nutzen können. Wir wissen, dass es einen Zeiger auf Char enthält, so dass wir auch legal darauf zugreifen können.

void func1(char* arr[]) 
{ 
    //function body 
} 
void func2(char** arr) 
{ 
    //function body 
} 

int main() 
{ 
    //x, y and z are pointer to char 
    char x[3]={'1', '2', '3'}; 
    char y[3]={'4', '5', '6'}; 
    char z[3]={'7', '8', '9'}; 

    //arr is pointer to char pointer 
    char* arr[3]={x, y, z}; 

    func1(arr); 
    func2(arr); 
} 
+2

Es gibt eine Reihe von Missverständnissen in dieser Antwort, die bereits [mindestens eine Person] verwirrt haben (https://stackoverflow.com/q/49075372/560648). Erstens sind 'char * argv []' und 'char ** argv' absolut äquivalent und bedeuten keine anderen Dinge. Zweitens ist "arr" kein Zeiger. Ich habe den Text nicht genau genug studiert, um andere spezifische Probleme zu identifizieren, aber diese sind bereits ernst genug, um einen Downvote und eine aufrichtige Hoffnung zu rechtfertigen, dass Sie diesen Beitrag noch einmal besuchen werden, bevor andere in die Irre geführt werden! –

+0

(absolut äquivalent _in diesem Kontext_, mindestens) –

+0

@LightnessRacesinOrbit Re: [Zweitens, 'arr' ist kein Zeiger] (https://stackoverflow.com/questions/27213580/difference-between-char-argv-and- char-argv-for-the-second-argument-to-main/27213637 # comment85157025_27214187) - vielleicht kommentieren was "arr" ist und welches 'arr' - ich sehe verschiedene Verwendungen in dieser Antwort. – chux

4

Sie sind genau das Gleiche. §5.1.2.2.2 der C11 Standardzustände:

The function called at program startup is named main . The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ } 

or with two parameters (referred to here as argc and argv , though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ } 

or equivalent;10) or in some other implementation-defined manner.

10) Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv , and so on.

klar, dass die Absicht ist, dass beide Erklärungen identisch zu sein. Darüber hinaus wird die Regel in §6.7.6 beschrieben.3/7:

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. ...

2

ein Array wie diese

char array[] 

macht es const deklarieren, was bedeutet, dass Sie nicht

char array[] = "hello"; 
array = "hey"; 

obwohl die zweite Zeichenfolge den folgenden Code

haben kann, ist kleiner und sollte passen Sie erhalten diesen Fehler

error: array type 'char [6]' is not assignable

wenn Sie **argv haben, können Sie

main(int argc, char **argv) 
{ 
    char **other_array; 
    /* 
    * do stuff with other_array 
    */ 
    argv = other_array; 
} 

schreiben, wenn Sie *argv[] dann

main(int argc, char *argv[]) 
{ 
    char **other_array; 
    /* 
    * do stuff with other_array 
    */ 
    argv = other_array; 
} 

gibt Ihnen diese Warnung

warning: assigning to 'const char **' from 'char **' discards qualifiers in nested pointer types

so ist es technisch eine kleine Optimierung haben, als ob Sie hatten geschrieben const