Pointer-Array-externe Frage

Lesezeit: 4 Minuten

Datei 1.c

int a[10];

Datei main.c:

extern int *a;

int main()
{
    printf("%d\n", a[0]);
    return 0;
}

Gibt mir einen Segfault! Was läuft schief?

Arrays werden zerlegt oder implizit in Zeiger konvertiert, wenn sie als Argument an eine Funktion übergeben oder auf der rechten Seite des Zuweisungsoperators in einen R-Wert konvertiert werden. Also sowas wie:

int array[10];
int* a = array;  //implicit conversion to pointer to type int

void function(int* a);
function(array);  //implicit conversion to pointer to type int

funktioniert prima. Aber das bedeutet nicht dass Arrays selbst Zeiger sind. Wenn Sie also ein Array wie einen Zeiger behandeln, wie Sie es getan haben, behandeln Sie den Array-Typ eigentlich so, als ob es ein Zeiger wäre, der die Adresse auf ein enthält int Objekt. Da Ihr Array eigentlich eine Folge von ist int Objekte und keine Zeiger auf int Objekte, Sie versuchen tatsächlich, auf einen Speicherort zu dereferenzieren, der auf keinen gültigen Ort zeigt (dh den ersten Slot in array ist ein numerischer ganzzahliger Wert wie z 0 was wie das Dereferenzieren einer NULL wäre). Deshalb segfaulten Sie also. Beachten Sie, dass, wenn Sie so etwas getan hätten:

int array[] = { 1, 2, 3, 4, 5};
int b = *array;

Das funktioniert immer noch, da array wird wiederum implizit in einen Zeiger auf den Speicherblock konvertiert, der eine Folge von ganzzahligen Werten enthält, und wird dann dereferenziert, um den Wert in der ersten Folge zu erhalten. Aber in Ihrem Fall, indem Sie Ihr Array für das aktuelle Codemodul als extern definierten Zeiger und nicht als Array deklarieren, wird die implizite Konvertierung in einen Zeiger übersprungen, die normalerweise durchgeführt wird, und das Array-Objekt einfach so verwenden, als ob es wäre waren ein Zeiger auf ein Objekt selbst, kein Array von Objekten.

  • Irgendwelche Vorschläge, wo ich mehr über dieses Verhalten lesen könnte?

    – estebro

    9. Dezember 2016 um 21:55 Uhr

  • Ich schaue mir die Compilerausgabe an, um dieses Verhalten zu sehen, es ist ziemlich offensichtlich, wenn Sie mit der grundlegenden Assemblersprache für Ihre Plattform vertraut sind. Sie werden sehen, dass die Array-Referenz von der Maschine tatsächlich genauso behandelt wird, als wäre es ein Zeigerzugriff. Diese Frage hier kann auch eine Hilfestellung sein.

    – Jason

    20. Dezember 2016 um 22:38 Uhr

  • Vielen Dank für die zusätzlichen Informationen (und dafür, dass Sie auf eine so alte Frage zurückgekommen sind).

    – estebro

    21. Dezember 2016 um 15:28 Uhr

Gut erklärt im C-Häufig gestellte Fragen. Und da ist eine Nachfolge. Das Bild im zweiten Link ist eine Million Dollar wert.

char a[] = "hello";
char *p = "world";

Geben Sie hier die Bildbeschreibung ein

Kurze Antwort: verwenden extern int a[].

Ein bisschen spät, ein Duplikat dieses Problems wurde gerade eingegeben (und geschlossen). Die Antworten hier erwähnen keine Header-Dateien …

Das Problem würde zur Kompilierzeit abgefangen, wenn Sie die Deklaration von Array setzen a in einer Header-Datei, wo es hingehört, anstatt es in die .c-Datei zu stecken. Die Header-Datei sollte dann in beiden .c-Dateien enthalten sein und der Compiler kann sehen, dass das, was Sie deklariert haben, falsch ist.

Ihre Header-Datei würde Folgendes enthalten:

extern int myarray[];

Sie erhalten so etwas wie “error: conflicting types for a„Wenn du erklärst a stattdessen als Zeiger.

Grundsätzlich müssten Sie Ihre main.c wie folgt schreiben:

extern int a[];

int main()
{
    printf("%d\n", a[0]);
    return 0;
}

Sehen Sie sich die Ausgabe des folgenden Codes an.

Datei1.c

#include <stdio.h>

extern int* my_arr;

void my_print()
{
  printf("%d", my_arr);
}

Haupt c

#include <stdio.h>

int my_arr[2] = {1,2};

extern void my_print();

void main()
{
    my_print();
}

Ausgang

1

innerhalb von File1.c my_arr ist eine Zeigervariable, die den Wert 1 hat. Dies bedeutet das 1. Element von my_arr[] wurde ihr zugeordnet. Wenn Sie dann *my_arr verwenden, um auf den Speicherort ox1 zuzugreifen, erhalten Sie einen Seg-Fehler, da Sie nicht auf ox01 zugreifen dürfen.

Warum dem my_arr-Zeiger 1 zugewiesen wurde (das erste Element von my_arr[])?

Hat damit zu tun, wie Assembler funktioniert. Lesen Dieser Artikel

Warum kann Ihr Code nicht auf 0x01 zugreifen?

Ich weiß, dass es damit zu tun hat, dass das Betriebssystem den Zugriff auf einige Adressräume durch Benutzercode nicht zulässt. Das ist alles was ich weiß. googeln Sie es, wenn Sie weitere Informationen wünschen.

1306530cookie-checkPointer-Array-externe Frage

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

Privacy policy