What the array?!?



  • kastrollux schrieb:

    Dieser Thread hat mein Vertrauen auf meine Einschätzungsfähigkeit anderer User zutiefst erschüttert.

    Dir gilt mein tiefstes Mitgefühl. Fühl' Dir von mir eine Kerze der Hoffnung entzündet. Wen meintest Du eigentlich?
    Meine kleine C-Forum-Welt ist die Tage auch beinahe zusammengebrochen, als ich den ein oder anderen Post mancher "alter Hasen" gelesen habe...



  • SeppJ schrieb:

    Die Hintergründe für die Geschichte dürften übrigens technischer Art sein: Die Größe der Funktionsparameter muss fix sein. Nun könnte man entweder sagen, dass die Funktion nur ein Array der Größe X annehmen kann, dann wäre man extrem inflexibel oder man macht es eben mit den Zeigern (was zudem noch performanter ist). Die Sprache Pascal macht es beispielsweise anders und man kann an eine Funktion nur Arrays bestimmter Größe übergeben. Du kannst dir sicherlich vorstellen, wie lustig es ist, eine Sortierfunktion zu schreiben und zu benutzen.

    Da es aber eigentlich die impliziete Konvertierung in Zeiger gibt, und man Arrays so über den Zeiger auf das erste Element und einen Zusatzparameter für die Länge übergeben kann, ist die impliziete Umwandlung von Array-Parametern mit Längenangabe in Pointer eigentlich überflüssig wie ein Kropf. Ich fände es besser (und logischer), wenn ein int[5] auch als Funktionsparameter ein int[5] bleiben würde. Wenn man es generisch haben will, nimmt man halt ein int* .



  • kastrollux schrieb:

    alte[.] Hasen

    Die hängen zu viel im C++ Forum rum.

    @Tachyon Ein Lichtblick, ein Mitstreiter, Wohoo! 😃



  • PrettyP schrieb:

    Meine kleine C-Forum-Welt ist die Tage auch beinahe zusammengebrochen, als ich den ein oder anderen Post mancher "alter Hasen" gelesen habe...

    Selbst die "alten Hasen" machen mal Fehler, sei es aus Flüchtigkeit oder Unwissenheit. Egal, wie viele Jahre man sich schon mit etwas beschäftigt, man lernt nie aus 😉

    Tachyon schrieb:

    SeppJ schrieb:

    Die Hintergründe für die Geschichte dürften übrigens technischer Art sein: Die Größe der Funktionsparameter muss fix sein. Nun könnte man entweder sagen, dass die Funktion nur ein Array der Größe X annehmen kann, dann wäre man extrem inflexibel oder man macht es eben mit den Zeigern (was zudem noch performanter ist). Die Sprache Pascal macht es beispielsweise anders und man kann an eine Funktion nur Arrays bestimmter Größe übergeben. Du kannst dir sicherlich vorstellen, wie lustig es ist, eine Sortierfunktion zu schreiben und zu benutzen.

    Da es aber eigentlich die impliziete Konvertierung in Zeiger gibt, und man Arrays so über den Zeiger auf das erste Element und einen Zusatzparameter für die Länge übergeben kann, ist die impliziete Umwandlung von Array-Parametern mit Längenangabe in Pointer eigentlich überflüssig wie ein Kropf. Ich fände es besser (und logischer), wenn ein int[5] auch als Funktionsparameter ein int[5] bleiben würde. Wenn man es generisch haben will, nimmt man halt ein int* .

    Ja, logischer fände ich das auch.



  • kastrollux schrieb:

    Dieser Thread hat mein Vertrauen auf meine Einschätzungsfähigkeit anderer User zutiefst erschüttert.

    👎 Damit kannst du sicher mit leben oder beantworte doch selbst eine solche Frage hinreichend zuverlässig, nachvollziehbar, und jederzeit gebrauchsfähig einsetzbar! 🕶
    Nur unqualifiziert hier motzen ist nicht so erwünscht, weil es nichts bringt! 😃

    daddeldu! :p



  • Das ist doch Erbsenzählerei.
    K&R hatten einen konkreten (und vor allem praktischen) Hintergrund bei ihrem Vorgehen: sie brauchten ein Werkzeug für ihr (auch heutzutage noch wohl nicht ganz unbekanntes) Betriebssystem, nämlich Unix.
    Stroustrup ist Professor und somit Anti-Praktiker, der brauchte etwas, womit er in seinen Vorlesungen bei den Studenten durch Eleganz/Plausibilität aus Akademikersicht glänzen konnte.
    C ist in erster Linie von Programmierern/Entwicklern/Praktikern für Programmierer/Entwickler/Praktiker konzipiert worden und nicht primär als Lernsprache.
    Die offensichtliche Tatsache, dass heute die Professoren ihre Studenten mit C konfrontieren, obwohl sie nachweislich (ich hatte schon mal einen Link zu einem passenden Herrn an der HTW Berlin genannt) selbst die Grundlagen nicht verstanden haben, finde ich einerseits schlecht (sie lehren ihren Studenten oft Fehler), andererseits gut (die Studenten kennen C, wenn auch nur bruchstückhaft und mit vielen Fehlern, aber dazu sind wir ja hier da;-).



  • Die ganze Sache wäre ohnehin einfacher, wenn Arrays richtige Wertsemantik hätten. So dass man ganze Arrays kopieren und zuweisen kann und nicht immer diese impliziten Pointer-Decays hat. Für Low-Level-Programmierung mag das zwar ein nützliches Feature sein, aber in C++ hat man zum Beispiel mit der array -Klasse etwas abstrahiert.



  • Wutz schrieb:

    Das ist doch Erbsenzählerei.
    K&R hatten einen konkreten (und vor allem praktischen) Hintergrund bei ihrem Vorgehen: sie brauchten ein Werkzeug für ihr (auch heutzutage noch wohl nicht ganz unbekanntes) Betriebssystem, nämlich Unix.
    Stroustrup ist Professor und somit Anti-Praktiker, der brauchte etwas, womit er in seinen Vorlesungen bei den Studenten durch Eleganz/Plausibilität aus Akademikersicht glänzen konnte.

    Bjarne Stroustrup war bei Bell Labs, als er C++ entwickelte - genau der selben Einrichtung, in der Brian Kernighan und Dennis Ritchie C entwarfen. Vorlesungen und Studenten hatte er zu dieser Zeit keine.


  • Mod

    cooky451 schrieb:

    Was wäre schlechter an folgender Regelung:

    void foo(int *v); // Funktioniert wie gewohnt
    void foo(int v[]); // Entweder verboten oder wie Zeiger
    void foo(int v[5]); // Es können nur Arrays der Größe 5 übergeben werden, sizeof(v) ergibt auch 5 * sizeof(int)
    void foo(int v[5][5]); // .. nur [5][5] Arrays.
    

    Dass es inkompatibel zu bestehendem Code wäre.



  • camper schrieb:

    Dass es inkompatibel zu bestehendem Code wäre.

    Wieso wusste ich dass das jetzt kommt? 😃
    Das ist ja kein Argument, solange wir nicht den ISO Standard schreiben 😃 Die Frage war ja, was logischer ist.
    (Abgesehen davon finde ich eh die sollten lieber die Sprache schön halten, als mit Typen wie _bool anzukommen. Compiler die aktuellen Code kompilieren können gibt's doch genug. Aber das ist ein ganz anderes Thema.)



  • _Bool ist eigentlich nicht dazu gedacht, direkt benutzt zu werden. IdR bindet man stdbool.h ein und benutzt dann bool, true und false.

    Was die Arrays angeht, so ist es schwierig, diese Dinge zur Compilezeit festzustellen. Wenn ich jetzt

    void foo(int arr[5]);
    
    ...
    
    size_t i;
    int *ptr = malloc(7 * sizeof(int[5]));
    
    for(i = 0; i < 7; ++i) {
      foo(ptr + i * 5);
    }
    

    schreibe, ist es für einen Compiler schon schwer herauszufinden, ob das, was ich da mache, auch korrekt ist. Er muss es dementsprechend durchlassen, denn nichts ist nutzloser als ein Compiler, der nicht tut, was man ihm sagt.

    Es gibt in C99 ein Sprachmittel, dass es einem Compiler erlauben würde, in einfachen Fällen zu warnen:

    void foo(int arr[static 5]);
    

    Allerdings verhält sich gcc 4.6 (andere C99-Compiler habe ich nicht zur Hand) bei

    int a[3];
    foo(a); /* Undefiniert nach 6.7.5.3 (7) */
    

    selbst mit -Wall -Wextra -pedantic ruhig. Womöglich ändert sich das aber in zukünftigen Versionen.

    Der Vollständigkeit halber:

    ISO/IEC 9899:1999 6.7.5.3 (6) schrieb:

    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. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.



  • seldon schrieb:

    Was die Arrays angeht, so ist es schwierig, diese Dinge zur Compilezeit festzustellen. Wenn ich jetzt

    void foo(int arr[5]);
    
    ...
    
    size_t i;
    int *ptr = malloc(7 * sizeof(int[5]));
    
    for(i = 0; i < 7; ++i) {
      foo(ptr + i * 5);
    }
    

    schreibe, ist es für einen Compiler schon schwer herauszufinden, ob das, was ich da mache, auch korrekt ist. Er muss es dementsprechend durchlassen, denn nichts ist nutzloser als ein Compiler, der nicht tut, was man ihm sagt.

    Das wäre natürlich verboten, dafür gibt's ja int*. Folgendes ist ja auch nicht erlaubt:

    void foo(int bar[][5]);
    
    int main()
    {
      int **baz = malloc(..);
      for (..;..;..)
        baz[i] = malloc(..);
      foo(baz);
    }
    


  • Moment, jetzt bringst du Zeiger und Arrays durcheinander. Ein zweidimensionales Array enthält keinerlei Zeiger - die Dimensionierung ist nur eine Frage der Indexumrechnung.

    Es ist ohne Weiteres möglich,

    void foo(int a[][5]);
    
    ...
    
    int (*ptr)[5] = malloc(7 * sizeof(int[5]));
    foo(ptr);
    

    zu schreiben. Es geht sogar mit

    int arr[20];
    foo(arr);
    

    Dann entspricht a[2][2] in foo arr[12] außerhalb. Allerdings dürfte das ohne Cast eine Compilerwarnung auslösen.


Anmelden zum Antworten