C Fehler: vla-parameter
-
@TheCrazyDev64 sagte in C Fehler: vla-parameter:
/mnt/c/Users/theun/CLionProjects/the-raytracer-challenge/src/helper/matrix.c:18:45: warning: argument 7 of type ‘float[yB][xA]’ declared with mismatched bound argument 2 [-Wvla-parameter] > 17 | void mulMatrix(const size_t yA, const size_t xA, f32_t matrixA[yA][xA], const size_t yB, const size_t xB, > | ~~~~~~~~~~~~~~~ > 18 | f32_t matrixB[yB][xB], f32_t matrixC[yB][xA]) { > In file included from /mnt/c/Users/theun/CLionProjects/the-raytracer-challenge/src/helper/matrix.c:1: > /mnt/c/Users/theun/CLionProjects/the-raytracer-challenge/src/helper/matrix.h:43:22: note: previously declared as ‘float[yB][xB]’ with bound argument 5 > 42 | void mulMatrix(size_t yA, size_t xA, f32_t a[yA][xA], size_t yB, size_t xB, f32_t b[yB][xB], > | ~~~~~~~~~ > 43 | f32_t result[yB][xB]);
Genau. Das hier gehört alles zusammen und sagt dir, dass du es einmal mit Parameter #2 (xA) und einmal mit Parameter #5 (xB) deklariert hast.
-
@wob sagte in C Fehler: vla-parameter:
@Fragender sagte in C Fehler: vla-parameter:
Andere und vielleicht blöde Frage, aber wofür braucht man die Größenangabe bei der Parameterdeklaration, wenn diese eh nicht "fest" ist? Du willst ja Matrizen beliebiger Dimension multiplizieren, weshalb dann die Akrobatik mit f32_t a[yA][xA], anstatt einfach nur f32_t a[][]? Gewinnt man dadurch einen compile/runtime check?
Ohne Kenntnis der Größe (von allen Dimensionen bis auf die erste) kannst du die Position im Speicher nicht bestimmen.
Das war nicht das, was ich geschrieben hatte. Die Größe ist doch durch
size_t
bekannt.
-
@Fragender bin jetzt kein Experte, aber size_t ist einfach ein Typ je nach system, der Aussage wie groß ein Array maximal sein kann. Also z.b. kann man nur den 16bit Bereich ausfüllen. Size_t sagt also nicht aus, dass das automatisch dem Array zugeordnet wird
Mit meiner Schreibweise gibt man dem Compiler die Information, dass er damit klarkommt auf die richten Indexe zuzugreifen. Bei 1D Arrays ist das theoretisch vernachlässigbar, aber bei 2d nicht, da [1][0] im speicher nach [0][n] liegt
Zumindest ist das mein gefährliches Halbwissen
-
Meiner Auffassung nach, ist und bleibt es Aufgabe des Programmierers, die richtigen Größen zu übergeben. Das doppelt anzugeben, ändert daran ja nix... der Programmierer kann ja immernoch Nonsense übergeben, und der Compiler würde nicht meckern... Die "common practice"/das Pattern scheint mir deshalb nicht richtig zu sein.
-
@Fragender Da wird nichts doppelt angegeben.
Es werden die Dimensionen und der Anfang vom Array übergeben.
Hier wird aber der Pointer auf das Array hinter einem VLA versteckt, so dass man in der Funktion auch die Arrayschreibweise nehmen kann.
Was ab 2D-Arrays durchaus etwas übersichtlicher ist.
-
Macht es da nicht Sinn, eine Struktur zu definieren? Sowas wie
typedef struct tagArray2D { f32_t Elements[...][...]; // hier passende Deklaration, oder auch nur einen Zeiger für eine Art "ArrayView2D" unsigned int Rows; unsigned int Columns; } Array2D;
-
@DocShoe meines Wissens nach geht das nicht, da ein struct eine feste Größe hat. Ich könnte ein Pointer speichern, aber wenig Interesse das alles via malloc zu lösen
Vielleicht muss ich es aber sowieso via malloc lösen, weiß derzeit nicht wie es sich auf den Stack verhält
-
@Fragender die mulMatrix Funktion kann mit verschiedenen Matrizen umgehen. Daher brauche ich die Dimensionen. Und damit ich mir das Leben einfacher mache, sag ich dem Compiler dass der diese Zahlen nehmen kann zum berechnen der Speicherposition. Denn arr[1][0] liegt bei 1*dim2Size+0
Da dim2Size für eine 4x4 anders ist als für eine 2x2 kann der Compiler ohne die Angabe das nicht berechnenIch kann natürlich auch nur den Pointer annehmen und dann mit der obigen Rechnung selbst drauf zugreifen, aber das ist unlesbarer und hab auch Mal gesehen dass das via Array sogar minimal schneller sei
-
Du kannst das ja auch so lösen:
typedef struct tagArray2D { f32_t* Elements; unsigned int Rows; unsigned int Columns; } Array2D; void f( Array2D* arr ) { ... } void g() { f32_t data_1[10]5]; f32_t data_2[50]; Array2D arr; arr.Elements = data_1; // oder data_2 arr.Columns = 10; arr.Rows = 5; f( &arr ); }
Das
Array2D
ist dabei ein View, es besitzt die Daten nicht, sondern stellt dir nur eine Möglichkeit zur Verfügung, wie du auf die Daten "gucken" kannst.
-
@Fragender sagte in C Fehler: vla-parameter:
Andere und vielleicht blöde Frage, aber wofür braucht man die Größenangabe bei der Parameterdeklaration, wenn diese eh nicht "fest" ist? Du willst ja Matrizen beliebiger Dimension multiplizieren, weshalb dann die Akrobatik mit
f32_t a[yA][xA]
, anstatt einfach nurf32_t a[][]
? Gewinnt man dadurch einen compile/runtime check? Verstehe ich nicht.Das liegt daran wie C Arrays an Subroutinen übergibt, nämlich nach dem Übersetzen als reiner Zeiger ohne jede Information. Wenn das Array zum Übersetzungszeitpunkt bekannt ist, werden überall schon beim Übersetzen die passenden Werte eingesetzt. Ist das nicht der Fall weiß der Compiler nur, dass ein Array auf T übergeben wird. Wie groß es ist und wie viele Dimensionen das hat, ist ihm nicht bekannt.
VLAs in C haben so ihre Probleme, aber man kann zumindest sie problemlos an Subroutinen in der passenden Größe übergeben. Wer es komfortabler will, muss eine andere Sprache nutzen.
-
@TheCrazyDev64 sagte in C Fehler: vla-parameter:
@DocShoe meines Wissens nach geht das nicht, da ein struct eine feste Größe hat. Ich könnte ein Pointer speichern, aber wenig Interesse das alles via malloc zu lösen
Das ist der übliche Weg, unter anderem weil das mit all den historischen Codes und allen anderen Sprachen funktioniert. Wenn man mathematische Berechnungen durchführen will, dann wäre meine Empfehlung entweder C++ oder Fortran zu nehmen.
P.S. VLAs funktionieren in C++ nicht bzw. nur als proprietäre Erweiterung bei bestimmten Compilern.
-
@john-0 sagte in C Fehler: vla-parameter:
Das ist der übliche Weg, unter anderem weil das mit all den historischen Codes und allen anderen Sprachen funktioniert. Wenn man mathematische Berechnungen durchführen will, dann wäre meine Empfehlung entweder C++ oder Fortran zu nehmen.
Mit Blitz++ braucht man über Fortran nicht mehr nachzudenken.
-
@DocShoe sagte in C Fehler: vla-parameter:
Mit Blitz++ braucht man über Fortran nicht mehr nachzudenken.
Für Wissenschaftler ist die Komplexität von Fortran gegenüber C++ deutlich geringer, und auf die hochoptimierten Versionen von BLAS und LAPACK sollte man ohnehin nicht verzichten, so dass der Code so formuliert sein sollte, dass man leicht diese Libraries nutzen kann.
-
Wieso geht private/verstecken nicht? C++ kann doch nach C umgewandelt werden?!
-
Ach Scheiße, ich bin wieder im falschen Thema gelandet.