ProgrammierungC Entwickler

Erzählen Sie ausführlich über den Mechanismus der Übergabe von Arrays an Funktionen in der Programmiersprache C. Welche Risiken sind mit diesem Modell verbunden und wie kann man die sichere Arbeit mit Arrays innerhalb von Funktionen richtig organisieren?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In der Programmiersprache C werden Arrays nicht nach Wert an Funktionen übergeben. Wenn ein Array als Argument übergeben wird, erhält die Funktion tatsächlich einen Zeiger auf das erste Element des Arrays. Dies führt dazu, dass die Funktion das ursprüngliche Array und nicht eine Kopie davon modifiziert.

Zum Beispiel:

void fillArray(int arr[], int n) { for (int i = 0; i < n; ++i) arr[i] = i*i; } int main() { int myarr[5]; fillArray(myarr, 5); // ok }

Innerhalb der Funktion:

  • Es ist unmöglich, die Größe des ursprünglichen Arrays über sizeof(arr) zu erfahren – dies gibt die Größe des Zeigers zurück und nicht die Größe des Arrays.
  • Man kann nur mit dem Teil des Speichers arbeiten, dessen Größe man ausdrücklich übergeben hat.

Um korrekt und sicher mit Arrays zu arbeiten, kann man Folgendes tun:

  • Immer die Größe des Arrays als separates Argument übergeben;
  • Verwenden Sie Konstanten oder Makros als Wrapper für Größen;
  • Wenn es notwendig ist, das Array vor Änderungen zu schützen, übergeben Sie const int *arr.

Fangfrage

Frage: Ist es möglich, die Größe des übergebenen ursprünglichen Arrays innerhalb der Funktion über das Argument int arr[] mit sizeof(arr) zu erfahren?

Antwort: Nein, das ist nicht möglich! sizeof(arr) innerhalb der Funktion gibt die Größe des Zeigers auf den Typ zurück (zum Beispiel 4 oder 8 Byte), nicht die Größe des Arrays.

Beispiel:

void f(int arr[]) { printf("%zu\n", sizeof(arr)); // Größe des Zeigers, nicht des Arrays! } int main() { int x[10]; f(x); // Gibt normalerweise 8 (x86_64) oder 4 (x86) aus }

Beispiele für echte Fehler


Geschichte

In einem Industrieprojekt versuchten Funktionen zum Kopieren von Arrays, die Länge des Arrays zur Laufzeit zu berechnen, indem sie sizeof(arr)/sizeof(int) innerhalb der Funktion verwendeten. In der Praxis führte dies dazu, dass nur ein Teil des Arrays kopiert wurde, da die Größe immer 1 betrug (8/8), und die Daten auf unvorhersehbare Weise überschrieben wurden.


Geschichte

In einer Netzwerk-Anwendung nahm die Funktion zum Senden von Daten einen Puffer in Form eines Arrays ohne ausdrückliche Angabe seiner Größe an, weshalb der gesamte Puffer nicht gesendet werden konnte oder außerhalb der Grenzen des Arrays Müll gelesen wurde, was zu Übertragungsfehlern und Instabilität der Verbindung führte.


Geschichte

Bei der Erstellung einer Bibliothek zur Verarbeitung von Bildern versäumte der Programmierer, der Funktion zum Färben von Arrays von Bildern einen erforderlichen Größenparameter hinzuzufügen. Dies führte zu einem Pufferüberlauf und zum Absturz des Programms bei bestimmten Eingaben, was erst bei einem Integrationstest mit einem großen Bild entdeckt wurde.