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

Lesezeit: 6 Minuten

Benutzer-Avatar
Jhansi Rani

KODEX 1

#include<stdio.h>

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

KODEX 2

#include<stdio.h>

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

CODE 1 und CODE 2 beide geben die gleiche Ausgabe. aber Argument 2 der Hauptfunktion in CODE 1 und CODE 2 sind unterschiedlich. Ein Array von Zeigern wird zur Kompilierzeit über dem Datenabschnitt erstellt. argv ist ein Array von Zeigern. Dann sollten wir das Argument in der Hauptfunktion als Zeiger auf Zeiger auf Zeichen deklarieren, dh **argv. Wie ist es richtig, wie in CODE 1 zu deklarieren?

  • Der zweite Parameter ist in Bezug auf den Compiler in keiner Weise anders, das heißt char *argv[] ist nur gleichbedeutend mit char **argv. Das ist eher eine Frage des bevorzugten Codierungsstils.

    – Grzegorz Szpetkowski

    30. November 2014 um 13:23 Uhr


Benutzer-Avatar
bmargulies

Es ist grundlegend dafür char** x und char* x[] sind zwei Ausdrucksmöglichkeiten das gleiche. Beide deklarieren, dass der Parameter einen Zeiger auf ein Array von Zeigern erhält. Denken Sie daran, dass Sie immer schreiben können:

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

 x = &parray[0];

und verwenden Sie dann x identisch.

  • Abgesehen von der Verwendung von sizeof

    – Ed heilen

    30. November 2014 um 13:32 Uhr

  • IMO, diese Antwort würde erheblich verbessert, wenn Sie zumindest kurz darauf hinweisen würden, dass es einige Stellen in C gibt (wie die sizeof erwähnt von Ed Heal), wo sich Arrays befinden nicht Äquivalent zu Zeigern, und dass die “Array-Anpassung” in Funktionsparameterdeklarationen (nach denen die Frage fragt) sich von der “Array-Zerfall” in Ausdrücken unterscheidet (obwohl sie damit zusammenhängt). Als Referenzen könnten Sie z. B. Was ist ein moderner Begriff für „Array/Zeiger-Äquivalenz“? und Ausnahme für Array, das nicht in einen Zeiger zerfällt?

    – Ilmari Karonen

    14. März 2018 um 12:55 Uhr


  • @Ilmari-Karonen IMHO ist diese Antwort richtig (das Beispiel ist jedoch falsch). Nur weil eine Funktionssignatur geschweifte Klammern enthält, bedeutet das nicht, dass es sich um eine Array-Variable handelt! Die Wahrheit ist, C nimmt an, dass es sich um einen normalen Zeiger handelt! Das ist sogar die einzige logische Entscheidung, die man von C erwarten könnte, denn wenn dort WIRKLICH eine Array-Variable angenommen würde, könnte ihr nichts zugewiesen werden (Array-Variable hat keinen separaten Speicher, der für sich selbst spezifisch ist, wie dies bei Zeigern der Fall ist). Daher glaube ich, dass dies nur eine vereinfachende Notation ist (charArr[]) bereitgestellt von C, was genau dasselbe ist wie die andere Notation (char*arr).

    – aderchox

    20. November 2018 um 9:57 Uhr

Grundsätzlich ist char* argv[] bedeutet 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 er enthält die Adresse des ersten Elements.

In dem unten angegebenen Code ist x im char-Array x also ein Zeiger auf das erste Element, ‘1’, das ein Zeichen ist. Es ist also ein Zeiger auf ein Zeichen.

Und im Array arr ist arr das erste Element des Zeigers, x, das selbst ein Zeiger auf ein Zeichen ist. Es ist also ein Zeiger auf einen anderen Zeiger.

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

Während Sie etwas in einer Funktion erhalten, ist die Grundregel, dass Sie die Art der Sache angeben müssen, die Sie erhalten. Also entweder sagst du einfach, dass du ein char** erhalten möchtest, oder du kannst auch char* arr sagen[].

Im ersten Fall brauchen wir nichts Komplexes zu denken. Wir wissen einfach, dass wir ein Array von char* empfangen. Kennen wir das nicht? Also erhalten wir es und verwenden es.

Im zweiten Fall ist es einfach, wie ich oben erklärt habe, dass arr ein char** ist, Sie können dies als Typ angeben und sicher empfangen. Jetzt kennt das System die Art 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, als hätten wir die Startadresse des Arrays erhalten, wir können sicherlich zu den nächsten Elementen gehen, und da wir seinen Typ kennen, wissen wir, was er enthält und wie wir ihn weiter verwenden können. Wir wissen, dass es einen Zeiger auf char enthält, sodass 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);
}

  • Diese Antwort enthält eine Reihe von Missverständnissen, die bereits mindestens eine Person verwirrt haben. Zuerst, char* argv[] und char** argv sind absolut gleichwertig und bedeuten überhaupt nichts Unterschiedliches. Zweitens, arr ist nicht ein Zeiger. Ich habe den Text nicht genau genug studiert, um andere spezifische Probleme zu identifizieren, aber diese sind bereits schwerwiegend, um eine Ablehnung und eine aufrichtige Hoffnung zu rechtfertigen, dass Sie diesen Beitrag erneut besuchen, bevor andere in die Irre geführt werden!

    – Leichtigkeitsrennen im Orbit

    2. März 2018 um 18:54 Uhr


  • (absolut gleichwertig in diesem Zusammenhangwenigstens)

    – Leichtigkeitsrennen im Orbit

    2. März 2018 um 19:00 Uhr

  • @LightnessRacesinOrbit Betreff: Zweitens, arr ist kein zeiger – vielleicht was kommentieren arr ist und welche arr – Ich sehe verschiedene Verwendungen in dieser Antwort.

    – chux – Wiedereinsetzung von Monica

    2. März 2018 um 19:30 Uhr

  • @chux: Guter Punkt. Ich habe auf den Code-Kommentar geantwortet und vergessen, das zu sagen!

    – Leichtigkeitsrennen im Orbit

    2. März 2018 um 19:34 Uhr

  • Ich stimme zu, dass diese Antwort irreführend ist! Zum einen ist Arrayname KEIN Zeiger! Es ist die “Adresse” des ersten Elements des Arrays, es enthält es nicht! Da es keinen separaten Speicherort hat! Bitte beheben Sie diese Fehler oder entfernen Sie die Antwort.

    – aderchox

    20. November 2018 um 9:36 Uhr

Sie sind genau gleich. §5.1.2.2.2 des C11-Standards besagt:

Die beim Programmstart aufgerufene Funktion wird benannt main. Die Implementierung deklariert keinen Prototyp für diese Funktion. Es muss mit einem Rückgabetyp von definiert werden int und ohne Parameter:

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

oder mit zwei Parametern (hier als argc und argvobwohl beliebige Namen verwendet werden können, da sie lokal für die Funktion sind, in der sie deklariert sind):

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

oder gleichwertig;10) oder auf eine andere implementierungsdefinierte Weise.

10) Also, int kann durch einen Typedef-Namen ersetzt werden, der als definiert ist intoder die Art von argv kann geschrieben werden als char ** argvusw.

Die Absicht ist eindeutig, dass beide Erklärungen identisch sind. Darüber hinaus wird die Regel in §6.7.6.3/7 beschrieben:

Eine Deklaration eines Parameters als ”array of Typ” soll auf ”qualifizierter Zeiger auf angepasst werden
Typ”, wobei die Typqualifizierer (falls vorhanden) diejenigen sind, die in der angegeben sind [ and ] der Array-Typ-Ableitung. …

Benutzer-Avatar
jde-kind

[EDIT] Verwenden von GCC zum Zeitpunkt des Kommentars wahrscheinlich GCC 7.2

Deklarieren eines Arrays wie diesem

char array[]

macht es konstant, was bedeutet, dass Sie den folgenden Code NICHT haben können

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

obwohl die zweite Zeichenfolge kleiner ist und passen sollte, erhalten Sie diesen Fehler

Fehler: Array-Typ ‘char [6]’ ist nicht zuweisbar

Wenn Sie haben **argv Du kannst schreiben

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

Wenn Sie haben *argv[] dann

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

gibt Ihnen diese Warnung

Warnung: Die Zuweisung zu ‘const char **’ von ‘char **’ verwirft Qualifizierer in verschachtelten Zeigertypen

also ist es technisch gesehen eine kleine optimierung wie du geschrieben hast const

1368440cookie-checkUnterschied zwischen char *argv[] und char **argv für das zweite Argument von main() [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy