Was ist der Grund dafür, die Zuweisung an Arrays zu verhindern?

Lesezeit: 8 Minuten

Benutzer-Avatar
Maisstängel

Ich habe versucht, dies zu googlen und gelesen:

  • Warum können keine Arrays gleichen Typs und gleicher Größe zugewiesen werden?
  • Arrays zuweisen
  • Weisen Sie die Array-Anweisung in c zu

Aber sie alle sagen das Offensichtliche: Sie können Arrays nicht zuweisen, weil der Standard es so sagt. Das ist großartig und alles, aber ich will es wissen warum der Standard enthält keine Unterstützung für die Zuweisung an Arrays. Das Standardkomitee diskutiert die Dinge im Detail, und ich wäre überrascht, wenn sie nie darüber gesprochen hätten, Arrays zuweisbar zu machen. Angenommen, sie haben es besprochen, müssen sie eine Begründung dafür haben, Arrays nicht zuzuweisen.

Ich meine, wir können ein Array in eine Struktur einfügen und der Struktur problemlos zuweisen:

struct wrapper
{
    int array[2];
};

struct wrapper a = {{1, 2}};
struct wrapper b = {{3, 4}};
a = b; // legal

Die direkte Verwendung eines Arrays ist jedoch verboten, obwohl es effektiv dasselbe bewirkt:

int a[2] = {1, 2};
int b[2] = {3, 4};
a = b; // Not legal

Was ist die Begründung des Standardausschusses für das Verbot der Zuweisung an Arrays?

  • Ich denke, die Antwort in stackoverflow.com/questions/14826952/… würde Ihnen genug Grund geben

    – Daniel A. Weiß

    10. Januar 2015 um 21:35 Uhr

  • Um es klar zu sagen: Sie suchen keinen alten Einwand gegen die Zuweisung von Arrays, Sie wollen speziell Dokumentation des Normenausschusses, der die Zuordnung von Arrays prüft und ablehnt. Ist das richtig?

    – Aaron Golden

    10. Januar 2015 um 21:38 Uhr

  • @DanielA.White Also liegt es am Zeigerverfall?

    – Saschoalm

    10. Januar 2015 um 21:38 Uhr

  • @Leute, die denken, dass dies hauptsächlich auf Meinungen basiert: Es ist nicht; Ich bin neugierig auf historische Diskussionen, die das Standardkomitee geführt hat (vorausgesetzt, sie haben), und wie diese Diskussionen zu dem Schluss kamen, dass dies nicht unterstützt wird.

    – Maisstängel

    10. Januar 2015 um 21:38 Uhr


  • Einige frühere C tat ermöglichen Array-Zuweisungen in ausgewählten Situationen. stackoverflow.com/questions/18412094/…`

    – chux – Wiedereinsetzung von Monica

    10. Januar 2015 um 21:51 Uhr


In C kopiert die Zuweisung den Inhalt eines Objekts fester Größe in ein anderes Objekt fester Größe. Dies ist gut definiert und für skalare Typen (Ganzzahlen, Fließkomma, Zeiger, komplexe Typen seit C99) ziemlich einfach zu implementieren. Die Zuweisung von Strukturen ist fast genauso einfach; größere erfordern möglicherweise einen Anruf bei memcpy() oder Äquivalent, aber es ist immer noch einfach, da die Größe und Ausrichtung zur Kompilierzeit bekannt sind.

Arrays sind eine andere Sache. Die meisten Array-Objekte haben Größen, die erst zur Laufzeit bestimmt werden. Ein gutes Beispiel ist argv. Die Laufzeitumgebung erstellt ein Array von char für jedes Befehlszeilenargument und ein Array von char* enthält Zeiger auf die Argumente. Diese werden zur Verfügung gestellt main über argva char**und über die dynamisch zugewiesene char[] Arrays, deren Elemente argv zeigen auf.

C-Arrays sind eigenständige Objekte, auf die jedoch im Allgemeinen nicht als Objekte zugegriffen wird. Stattdessen wird über Zeiger auf ihre Elemente zugegriffen, und der Code durchläuft mithilfe von Zeigerarithmetik von einem Element zum nächsten.

Sprachen können so entworfen werden, dass sie Arrays als erstklassige Objekte mit Zuweisung behandeln – aber es ist kompliziert. Als Sprachdesigner müssen Sie entscheiden, ob ein Array aus 10 Ganzzahlen und ein Array aus 20 Ganzzahlen vom gleichen Typ sind. Wenn dies der Fall ist, müssen Sie entscheiden, was passiert, wenn Sie versuchen, das eine dem anderen zuzuordnen. Kopiert es die kleinere Größe? Verursacht es eine Laufzeitausnahme? Muss man ein hinzufügen Scheibe Operation, damit Sie mit Teilmengen von Arrays arbeiten können?

Wenn int[10] und int[20] unterschiedliche Typen ohne implizite Konvertierung sind, dann sind Array-Operationen unflexibel (siehe zum Beispiel Pascal).

All diese Dinge können definiert werden (siehe Ada), aber nur durch die Definition von Konstrukten auf höherer Ebene als das, was in C typisch ist. Stattdessen entschieden sich die Entwickler von C (hauptsächlich Dennis Ritchie) dafür, Arrays mit Operationen auf niedriger Ebene bereitzustellen. Es ist zugegebenermaßen manchmal unpraktisch, aber es ist ein Framework, das verwendet werden kann, um alle übergeordneten Array-Operationen jeder anderen Sprache zu implementieren.

Benutzer-Avatar
Jens

Der Grund ist im Grunde historisch. Es gab schon vor ISO C89 ein C, das hieß “K&R” C, nach Kernighan und Ritchie. Die Sprache wurde so konzipiert, dass sie klein genug ist, damit ein Compiler in einen (nach heutigen Maßstäben) stark begrenzten Speicher von 64 KB passen würde.

Diese Sprache erlaubte keine Zuweisung von Arrays. Wenn Sie Arrays gleicher Größe kopieren möchten, memcpy war für Sie da. Schreiben memcpy(a, b, sizeof a) Anstatt von a = b ist sicherlich keine große Komplikation. Es hat den zusätzlichen Vorteil, dass es auf Arrays und Array-Slices unterschiedlicher Größe verallgemeinerbar ist.

Interessanterweise die struct Aufgabenumgehung, die Sie auch erwähnen funktioniert nicht in K&R C. Sie mussten entweder Mitglieder einzeln zuweisen oder wieder verwenden memcpy. Das erste Ausgabe von K&R Die Programmiersprache C erwähnt struct Zuweisung als Feature für die zukünftige Implementierung in der Sprache. Was schließlich mit C89 passierte.

  • Kann der Downvoter einige Hinweise geben, was an meiner Antwort verbessert werden kann?

    – Jens

    11. Januar 2015 um 14:46 Uhr

Benutzer-Avatar
Deduplikator

Die Antwort ist einfach: Es war nie erlaubt, bevor das Komitee sich einmischte (sogar struct-Zuweisung wurde als zu schwer angesehen), und wenn man bedenkt, dass es einen Array-Verfall gibt, hätte es alle möglichen Auswirkungen interessant Konsequenzen.

Mal sehen, was sich ändern würde:

int a[3], b[3], *c = b, *d = b;
a = b; // Currently error, would assign elements
a = c; // Currently error, might assign array of 3?
c = a; // Currently pointer assignment with array decay
c = d; // Currently pointer assignemnt

Das Zulassen der Array-Zuweisung würde also (bis zu) zwei derzeit unzulässige Zuweisungen gültig machen.

Das ist jedoch nicht das Problem, es ist, dass nahezu identische Ausdrücke völlig unterschiedliche Ergebnisse haben würden.

Das wird besonders pikant, wenn man bedenkt, dass die Array-Schreibweise in Funktionsargumenten derzeit nur eine andere Schreibweise für Zeiger ist.
Wenn die Array-Zuweisung eingeführt würde, würde das noch verwirrender werden.
Nicht, dass nicht genug Menschen von den Dingen, wie sie heute sind, völlig verwirrt sind …

int g(int* x);  // Function receiving pointer to int and returning int
int f(int x[3]);// Currently the same. What afterwards? Change to value-copy?

  • Die Zuweisung zu Arrays ist derzeit nie sinnvoll, was kann also das Problem sein, die Sprache zu erweitern, um die Zuweisung zu Arrays zu ermöglichen (vielleicht von Arrays derselben Größe)? Ich sehe eigentlich keinen Raum für Verwirrung! Die Bedeutung des bestehenden Codes würde sich nicht ändern. Gibt es einen Eckfall, den ich vermisse? Wie auch immer, wir erlauben i=3aber nicht 3=ialso sind wir bereits mit einem Mangel an „Symmetrie“ um die Zuweisung einverstanden.

    – Aaron McDaid

    10. Januar 2015 um 22:17 Uhr


  • @AaronMcDaid: Das Problem ist eine völlig inkonsistente Semantik. Haben Sie auch die Zeile über Funktionsargumente gelesen? (Beispieldeklarationen hinzugefügt)

    – Deduplizierer

    10. Januar 2015 um 22:19 Uhr


  • Ah ja. Ich hatte an Array-Funktionsargumente gedacht, aber nur um zu denken, “sie sind verrückt”. Ich hatte vergessen, die Tatsache vollständig zu durchdenken, dass sie wie Zuordnungen zu Arrays ‘aussehen’. Ich möchte nur Arrays von der obersten Ebene der Funktionsparametertypen loswerden – sie sollten überhaupt nicht erlaubt sein. Tatsächlich denke ich, dass es sowieso so schnell wie möglich gemacht werden sollte, unabhängig von Vorschlägen, die Zuweisung an Arrays zuzulassen.

    – Aaron McDaid

    10. Januar 2015 um 22:26 Uhr


Benutzer-Avatar
Johannes Bode

Verstehen Sie, dass die Absicht war nicht um Array-Ausdrücke nicht zuweisbar zu machen; das war nicht das ziel1. Vielmehr ist dieses Verhalten auf eine Designentscheidung zurückzuführen, die Ritchie getroffen hat, indem er die Handhabung von Arrays im Compiler vereinfachte, dafür aber Array-Ausdrücke zu “Objekten zweiter Klasse” machte; Sie verlieren in den meisten Kontexten ihre “Array-Beschaffenheit”.

Lesen dieses Papier (insbesondere der Abschnitt mit dem Titel “Embryonic C”) für etwas Hintergrund; Ich habe auch eine ausführlichere Antwort hier.


1. Mit der möglichen Ausnahme von Perl oder PHP2, sind die meisten offenkundigen WTFs im Allgemeinen Konstruktionsunfälle oder das Ergebnis von Kompromissen; die meisten Sprachen sind es nicht absichtlich entworfen, um dumm zu sein.

2. Ich trolle nur ein bisschen; Perl und PHP sind ein reines Durcheinander.

Benutzer-Avatar
hackt

C ist so geschrieben, dass die Adresse des ersten Elements berechnet wird, wenn der Array-Ausdruck ausgewertet wird.

Auszug aus dieser Antwort:

Dies deshalb kann man sowas nicht machen

int a[N], b[N];
a = b;

denn beides a und b zum Zeiger auswerten Werte in diesem Zusammenhang; es ist gleichbedeutend mit Schreiben 3 = 4. Da ist eigentlich nichts in Erinnerung Shops die Adresse des ersten Elements im Array; der Compiler berechnet es einfach während der Übersetzungsphase.

Benutzer-Avatar
jamesqf

Vielleicht wäre es hilfreich, die Frage umzudrehen und zu fragen, warum Sie jemals Arrays (oder Strukturen) zuweisen möchten, anstatt Zeiger zu verwenden? Das ist viel sauberer und einfacher zu verstehen (zumindest wenn Sie sich das Zen von C angeeignet haben) und es hat den Vorteil, dass es nicht darüber hinwegtäuscht, dass sich unter der “einfachen” Zuweisung von Multi-Megabyte-Arrays viel Arbeit verbirgt.

1364940cookie-checkWas ist der Grund dafür, die Zuweisung an Arrays zu verhindern?

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

Privacy policy