const Array mit Variablen initialisieren
-
Hallo!
Folgendes Problem: (ich schwanke gerade zwischen "bestimmt ganz leicht" und "geht das überhaupt?")
Ich programiere gerade mit VisualDSP++ (Compiler für Signalprozessoren) und der zugehörigen Run-TimeLibary. Eine der Funktionen verlangt ein Argument der folgenden Form: "const float coeffs[]". (Soll heißen, er will einen Zeiger auf ein konstantes Array). Die verlangten Koeffizienten in coeffs kann ich allerdings erst zu Laufzeit ermitteln, wenn sie einmal da sind werden sie aber nicht mehr verändert, in sofern ist "const" schon richtig. Wie krieg ich meine berechneten Koeffizienten aus einem normalen Array am dümmsten in ein konstantes Array? Bei der Initialisierung kann ich sie ja nur explizit angeben, das wäre bei 1024 Werten aber etwas unkomfortabel.
Danke schonmal

Fledi
-
"const float coeffs[]". (Soll heißen, er will einen Zeiger auf ein konstantes Array
Nein das heißt es wird ein Array übergeben, welches du in der Funktion nicht verändern darfst. Eigentlich wird auch nur ein Zeiger auf ein Array übergeben. Und diesen kannst du sogar verändern, nur die Werte hinter dem Zeiger nicht. Deswegen finde ich diese Verwendung von const auch sehr naiv.
-
huhu,
irgendwie habe ich nicht ganz verstanden was du genau erreichen willst. Kannst du dein Problem nochmals in andere Worte fassen?
gruß
-
Ich kann in der Funktion sowieso nix ändern, die Funktion ist ja nicht von mir, sondern gehört zur Run-Time Libary. (Hatte ich wohl nicht explizit erwähnt, sorry dafür). Ob ich das jetzt schön finde oder nicht, ich muss nunmal damit arbeiten.
Ich muss ihm dafür aber eben zwingendermaßen ein Array des Datentypes const float übergeben(bzw. den Zeiger darauf) sonst meckert der Compiler. Und ich hab (ebenfalls zwingendermaßen) ein Array des Datentypes float. Die Frage ist: Wie mach ich aus dem einen das andere?
-
Paul Müller schrieb:
Deswegen finde ich diese Verwendung von const auch sehr naiv.
[ ]Du verstehst die Konzepte hinter constPaul Müller schrieb:
Und diesen kannst du sogar verändern, nur die Werte hinter dem Zeiger nicht.
[ ]Du verstehst den Begriff der Wertübergabe
[ ]Du hast schon einmal etwas vonconst_castgehört@fledi: Wenn du ein normales (nicht konstantes) Array übergibst, passt das schon. Ein nicht konstantes Array ist immer auch ein konstantes. Nur umgekehrt hast du ein Problem.
-
Fledi schrieb:
Ich muss ihm dafür aber eben zwingendermaßen ein Array des Datentypes const float übergeben(bzw. den Zeiger darauf) sonst meckert der Compiler. Und ich hab (ebenfalls zwingendermaßen) ein Array des Datentypes float. Die Frage ist: Wie mach ich aus dem einen das andere?
Das geht automatisch:
void foo(const float coeffs[]) {} int main() { float arr[5]= {.1,.2,.3,.4,.5}; foo(arr); }foo sagt nur, dass es coeffs nicht ändert. Du kannst ihm aber natürlich ein array geben, dass DU ändern kannst.
-
checklist schrieb:
Paul Müller schrieb:
Deswegen finde ich diese Verwendung von const auch sehr naiv.
[ ]Du verstehst die Konzepte hinter constScheinbar besser als du. Deine Aussage bestätigt mich aber in meiner Vermutung, dass vielen nicht klar ist, was sie eigentlich damit bewirken.
checklist schrieb:
Paul Müller schrieb:
Und diesen kannst du sogar verändern, nur die Werte hinter dem Zeiger nicht.
[ ]Du verstehst den Begriff der WertübergabeIm Gegensatz zu dir schon. Der Wert ist vom Typ nicht konstanter Zeiger auf konstanten Float. Und deswegen kannst du den Zeiger ändern, aber nicht den Wert.
Ich verstehe auch nicht, was du mir eigentlich mitteilen willst.checklist schrieb:
[ ]Du hast schon einmal etwas vonconst_castgehörtDas war nicht die Frage. Natürlich kann man jeden Datentyp casten bis es qualmt. Nur ob das Sinn macht ist eine andere Frage. Wenn er seine Koeffizienten aus einem ROM holt bringt dir auch dein Cast nichts mehr.
Noch was zum Nachdenken für dich:
/* gcc -c -Wall -Wextra -pedantic const.c -o /tmp/const.o */ int main(void) { int a ; /* I */ int const b = a; /* II */ int const * c ; /* III */ int const * const d = &a; /* VI */ int * const e = &a; /* V */ const int f = a; /* II */ const int * g ; /* III */ const int * const h = &a; /* VI */ a = 42; (void)b; c = &a; (void)d; (void)e; (void)f; g = &a; (void)h; /* Wie ersichtlich, sind alle Deklarationen mit const-Qualifizierer vor dem Bezeichner konstant. Diese Regel wird bei f durch die Schreibweise von const vor dem Typen verletzt. */ return 0; }
-
Paul Müller schrieb:
checklist schrieb:
Paul Müller schrieb:
Und diesen kannst du sogar verändern, nur die Werte hinter dem Zeiger nicht.
[ ]Du verstehst den Begriff der WertübergabeIm Gegensatz zu dir schon. Der Wert ist vom Typ nicht konstanter Zeiger auf konstanten Float. Und deswegen kannst du den Zeiger ändern, aber nicht den Wert.
Ich verstehe auch nicht, was du mir eigentlich mitteilen willst.Klar kannst du den Zeiger verändern, aber der Aufrufer bemerkt davon gar nichts, weil du ihn nicht als Referenz übergibst. Wenn ein
float *const coeffsverlang wäre, dann ist das naiv (es behütet dich nur vor Flüchtigkeitsfehlern innerhalb der Funktion). Aber um das geht es ja nicht.Ich gebe zu, deine Aufgabe stellt mich vor unlösbare Rätsel: Warum verrätst du die einzige Schwierigkeit schon durch Nummerierung? Warum codest du nicht direkt in tmp? Was hat das für einen Bezug zum Problem? Wo wird eine Regel verletzt?
-
Paul Müller schrieb:
Wie ersichtlich, sind alle Deklarationen mit const-Qualifizierer vor dem Bezeichner konstant.
Diese Regel wird bei f durch die Schreibweise von const vor dem Typen verletzt.Ich bin zwar auch fan von int const gegenüber const int - aber da wird nichts verletzt.
Du liest es einfach falsch. Richtig rum liest man von rechts nach links:
const intinteger (, der) konstant (ist)
int const
konstanter integermit Zeigern gehts auch easy:
const int * const
konstanter zeiger auf integer (, der) konstant (ist)int const * const
ist schöner, weil man so liest:
konstanter zeiger auf konstanten integeraber falsch oder kompliziert oder so ist hier nichts. Einfach von rechts nach links lesen.
-
checklist schrieb:
Klar kannst du den Zeiger verändern, aber der Aufrufer bemerkt davon gar nichts, weil du ihn nicht als Referenz übergibst. Wenn ein
float *const coeffsverlang wäre, dann ist das naiv (es behütet dich nur vor Flüchtigkeitsfehlern innerhalb der Funktion). Aber um das geht es ja nicht.Dir scheint nicht ganz klar zu sein, welche Erwartungen im Allgemeinen an ein const gestellt werden. Vielen ist eben nicht klar, dass damit nicht der ganze Ausdruck konstant wird. Ganz zu schweigen davon, was bei der Parameterübergabe passiert. Und das sind nicht nur reine Anfängerfehler. Auch Leute die schon länger mit C oder C++ programmieren, wissen dies nicht. Umso wichtiger ist es einen Anfänger darauf hinzuweisen. Und ihn nicht schnell zu den Unwissenden mit abzustellen.
checklist schrieb:
Ich gebe zu, deine Aufgabe stellt mich vor unlösbare Rätsel: Warum verrätst du die einzige Schwierigkeit schon durch Nummerierung?
Weil es kein Rätsel ist. Wenn es dir aber Fragen aufwirft, so soll es dir helfen diese zu lösen.
checklist schrieb:
Warum codest du nicht direkt in tmp?
In was für ein temp und wozu? Hier geht es um Zuweisbar oder nicht Zuweisbar, und nicht um 100€ bei Wer wird Millionär.
Zugegeben man hätte noch ein paar mehr Spielereien mit einbauen können, um alle Fälle zu zeigen. Du darfst aber gerne selber rum experimentieren.checklist schrieb:
Wo wird eine Regel verletzt?
Wie man sieht schaust du nur halb hin. Der Text besteht aus zwei Sätzen.
Die aufgestellte Regel heißt:
"Ein Bezeichner ist konstant, wenn vor ihm const steht. Das funktioniert natürlich nur solange const hinter der Typenkennzeichnung steht."
Ist da jetzt etwas falsch dran oder unverständlich?
-
Btw, wer es noch nicht kennt: http://www.cdecl.org/ . C gibberish
English
-
Paul Müller schrieb:
Die aufgestellte Regel heißt:
"Ein Bezeichner ist konstant, wenn vor ihm const steht. Das funktioniert natürlich nur solange const hinter der Typenkennzeichnung steht."
Ist da jetzt etwas falsch dran oder unverständlich?Ja und wessen Name auf r endet, der hat immer recht. Nur Paul Müller verletzt diese Regel. :p
Deine "Regel" ist einfach falsch. Das ist das Problem.
Wie gesagt: man liest von rechts nach links (bzw von innen nach aussen, wenn es klammern gibt).
-
Die Regel wäre falsch, wenn sie nicht stimmen würde. Sie schließt aber nicht aus, dass du const nicht davor schreiben darfst. Insofern macht sie also Sinn, dass man sagen kann, der Bezeichner ist immer konstant, wenn direkt const davor steht. Diese Eindeutigkeit ist aber bei einem const am Anfang nicht gegeben. Und zwar weder für den Bezeichner, noch für den Typ. Da es lediglich eine Ausnahme ist, die es erlaubt dort const davor zu schreiben.
Ich hätte aber auch einfach den Kommentar aus dem Codeschnipsel vorher löschen können, dann gäbe es diese Diskussion nicht.
-
Huch, was hab ich da angerichtet? Nicht streiten, bitte
Mein Problem lag an einer anderen Stelle, ich hab die Compilermeldung nur falsch interpretiert. Ihr habt trotzdem geholfen, sonst hätte ich noch ewig gesucht.
Jetzt hab ich endlich ne Echtzeitfilterbank
Danke schön!
-
Paul Müller schrieb:
Die Regel wäre falsch, wenn sie nicht stimmen würde. Sie schließt aber nicht aus, dass du const nicht davor schreiben darfst. Insofern macht sie also Sinn, dass man sagen kann, der Bezeichner ist immer konstant, wenn direkt const davor steht.
Nur der umkehrschluss ist nicht korrekt.
Die variable ist zwar immer konstant wenn direkt links neben ihr const steht, aber sie ist noch lange nicht immer nicht-const wenn das nicht der Fall ist.Die richtige Regel ist: von rechts nach links lesen (bzw von innen nach aussen, wenn es klammern gibt). Diese Regel ist immer korrekt.
Deine Regel ist zB in folgendem Code falsch:
int t(int const foo[]) { ++foo; return *foo; }foo ist nicht const. foo ist ein zeiger auf konstante ints.
-
Das Problem liegt aber eher an deiner unkonventionellen Art einen Zeiger zu deklarieren, als an meiner Merkregel. Die zwar genauso valide ist, wie const davor zu schreiben, aber diese inkonsistente Syntax trägt nicht gerade zur Erleuchtung bei. Ich muss auch sagen, dass ich diese Art der Zeigerübergabe mittlerweile soweit verdrängt habe, dass ich neulich erst mal nachsehen musste, was das eigentlich sein soll.
Ich will hier aber niemanden bekehren, sich eindeutig auszudrücken, was sonst eigentlich immer die Mathematiker gerne machen. Der Code-Schnipsel sollte lediglich zeigen, dass ein Wert nicht gleich const ist, nur weil const davor steht.
Btw, hat dein Beispiel einen weiteren Nachteil. Es ist unmöglich den Zeiger konstant zu bekommen.
-
Paul Müller schrieb:
Das Problem liegt aber eher an deiner unkonventionellen Art einen Zeiger zu deklarieren, als an meiner Merkregel.
Oder aber die Merkregel ist Schrott?
Es gibt ja massig Ausnahmen was ich alles nicht darf damit die Merkregel passt...Ich finde ebenfalls int const besser als const int. Aber das ändert nichts daran dass man C++ Code korrekt lesen können muss und deine "Regel" passt da einfach nicht rein. Viel einfacher ist es, es richtig zu lernen: von rechts nach links lesen. So lassen sich auch komplexe Typen lesen.
-
Paul Müller schrieb:
"const float coeffs[]". (Soll heißen, er will einen Zeiger auf ein konstantes Array
Nein das heißt es wird ein Array übergeben, welches du in der Funktion nicht verändern darfst. Eigentlich wird auch nur ein Zeiger auf ein Array übergeben. Und diesen kannst du sogar verändern, nur die Werte hinter dem Zeiger nicht. Deswegen finde ich diese Verwendung von const auch sehr naiv.
Warum? Dem Aufrufer wird garantiert, dass (aus seiner Sicht) nichts geändert wird, was er der Funktion übergibt. Was ist daran naiv?
-
Oder aber die Merkregel ist Schrott?
Ja, okay du hast Recht.
Ich hasse es, wie in diesem Forum all meine Falschaussagen auseinandergenommen werden... Vielleicht sollte ich mir einen neuen Nick suchen. Unter diesem hier nimmt mich ja sowieso keiner mehr ernst.
-
Paul Müller schrieb:
Ich hasse es, wie in diesem Forum all meine Falschaussagen auseinandergenommen werden...
Das ist nichts persönliches, es liegt eher an dem "Falsch" in den Aussagen. Man ist hier eben sehr penibel.