Warum akzeptieren die Absolutwertfunktionen in C keine konstanten Eingaben?
Lesezeit: 5 Minuten
Benutzer24205
In C ist der Prototyp für die Absolutwertfunktion (die einen Float akzeptiert).
float fabsf( float );
Warum akzeptiert dieser Prototyp keinen konstanten Wert wie diesen:
float fabsf( float const );
fabsf ändert den Wert der Eingabe nicht, oder?
Wenn ich eine Funktion habe, die eine Eingabe akzeptiert und fabsf aufruft, muss ich dann vermeiden, die Eingabe als const anzugeben?
Was ist der angemessene Weg, um in dieser Situation mit konstanter Korrektheit umzugehen?
const ist hier überflüssig, was stellst du dir vor?
– MM
13. Dezember 2019 um 4:48 Uhr
@MM Ich gehe davon aus, dass es zu einem Kompilierzeitfehler kommen würde, wenn ich versuchen würde, den Wert der Eingabe innerhalb der Funktion zu ändern. Ist das falsch?
– Benutzer24205
13. Dezember 2019 um 5:05 Uhr
Da der Parameter innerhalb der Funktion eine lokale Kopie ist, fügt das Hinzufügen von const ist völlig bedeutungslos.
– Ludin
13. Dezember 2019 um 9:35 Uhr
“fabsf ändert den Wert der Eingabe nicht, oder?” Woher wissen Sie das? Der Parameter wird als Wert übergeben.
– David Schwartz
14. Dezember 2019 um 18:43 Uhr
Der folgende Code ist legal C: float const x = -1.0; float y = fabsf(x); so kommt es mir vor fabsftut konstante Eingaben akzeptieren. Es gibt keine Möglichkeit zu sagen: „Du kannst mir eins reichen float nach Wert, aber Sie können a nicht übergeben const float.” (Und wie wir in den Antworten sehen, bietet C keine Möglichkeit dazu benötigen dass die Eingabe einer Funktion a ist float const.)
– David K
14. Dezember 2019 um 21:55 Uhr
MM
C verwendet Wertübergabe. Der Wert für den Parameter einer Funktion ist eine Kopie des Arguments, das Sie angeben.
Es ist in Ordnung, sowohl konstante als auch nicht konstante Gleitkommazahlen zu kopieren, und das Ergebnis ist eine nicht konstante Gleitkommazahl.
Es ist ähnlich wie bei der Zuweisung:
const float f = 5.5f;
float g = f; // OK
Tatsächlich gibt die Sprache an, dass der Wert eines Ausdrucks niemals sein kann constdh wenn ein Wert aus einer Variablen gelesen wird, wird dieser Wert nicht const auch wenn die Variable war.
die fleißige Biene
Bearbeiten
Wie MM kommentierte, über Parameter in Prototypen das const wird ignoriert. Die bearbeitete Quelle der ursprünglichen Antwort (siehe unten) zeigt dies:
Diese Quelle wird nicht ohne Fehlermeldung kompiliert.
Die Funktion correct() liest den gegebenen Wert, ändert sein Vorzeichen und gibt den negierten Wert zurück.
Die Funktion erroneous() scheint effektiv dasselbe zu tun, außer dass es eine Zuweisung zum Parameter gibt. Aber wie der Parameter ist const Das ist nicht erlaubt.
Als nächstes die Funktion changer() wird wie die beiden zuvor funktionieren, aber es gibt keine Fehler.
Schauen wir uns die Aufrufseite an:
float f = 3.14159;
float g = correct(f); // or erroneous(f) or changer(f)
Die Variable f als Argument angegeben werden kopiert in den Parameter value. Es wird sich nie ändern, selbst wenn changer() wird angerufen werden.
Vielleicht möchten Sie Parameter als eine Art lokaler Variablen betrachten. Tatsächlich werden sie im generierten Maschinencode meistens so behandelt.
Also, warum siehst du const manchmal? Sie sehen es, wenn a Zeiger ist als Parameter definiert.
Wenn Sie den Wert nicht wollen wies auf geändert werden, müssen Sie hinzufügen const; aber an der richtigen Stelle!
Die Frage bezieht sich jedoch auf Prototypen, den Prototypen float fabsf( float const ); hat nichts mit der Funktionsimplementierung zu tun (die nicht wiederholt werden muss const), eigentlich die const wird im Prototypen komplett ignoriert
– MM
13. Dezember 2019 um 8:25 Uhr
Kann const in Funktionsdefinitionen gehen, ohne in den Prototyp zu gehen?
– Benutzer24205
13. Dezember 2019 um 17:28 Uhr
@ user24205 Ja, das kann es
– Daniel Jour
14. Dezember 2019 um 7:43 Uhr
Da die C-Sprache Pass-by-Value-Semantik verwendet, irgendein Argument, das Sie ihm übergeben, obwohl es intern geändert werden könnte, wirkt sich nicht direkt auf den Wert aus, den Sie übergeben.
Das bedeutet aus Sicht des Anrufers, float fabsf( float ); und float fabsf( const float ); sind gleich. Es macht also keinen Sinn, den Parameter zu machen const.
Wo es tut sinnvoll einzusetzen const ist, wenn der Parameter, den Sie übergeben, ein Zeiger ist, zum Beispiel:
void print_string(char *str)
Diese Funktion kann, entgegen dem, was der Name vermuten lässt, den angegebenen Zeiger dereferenzieren und ändern, worauf er zeigt, dh str[0] = 'x', um zu einer Änderung zu führen, die von der aufrufenden Funktion sichtbar ist. Wenn diese Funktion so definiert wäre:
void print_string(const char *str)
Dem Aufrufer wird sichergestellt, dass die Funktion keine Änderungen an what vornehmen kann str verweist auf.
“Der Aufrufer ist sicher, dass die Funktion keine Änderungen vornehmen kann …” ist nicht wahr. Die Funktion kennt die Adresse der Daten und kann sie daher ändern, z. B. mit: ((char*)str)[0] = 'f'. Das const ... * in der Argumentationsliste steht daher nur eine “Absichtserklärung”.
– Oromoiluig
15. Dezember 2019 um 10:54 Uhr
Daniel Jour
So fügen Sie eine sprachjuristische Perspektive hinzu:
Damit zwei Funktionstypen kompatibel sind, müssen beide kompatible Rückgabetypen angeben. Darüber hinaus müssen die Parametertyplisten, falls beide vorhanden sind, in der Anzahl der Parameter und in der Verwendung des Auslassungszeichens übereinstimmen; entsprechende Parameter müssen kompatible Typen haben.
[..]
Bei der Bestimmung der Typenkompatibilität und eines zusammengesetzten Typs, [..] jeder Parameter, der mit qualifiziertem Typ deklariert ist, wird so behandelt, als hätte er die nicht qualifizierte Version seines deklarierten Typs.
N1570 6.7.6.3/15
Das heißt, diese beiden sind kompatibel:
void foo(int const);
void foo(int);
Daher können Sie den Prototyp mit oder ohne schreiben const (also ohne macht mehr Sinn; weniger tippen/lesen) und hinzufügen kann const in der Funktionsdefinition, wenn Sie vermeiden möchten, dass der (kopierte – Aufruf nach Wert!) Parameter innerhalb des Funktionskörpers versehentlich geändert wird.
13116500cookie-checkWarum akzeptieren die Absolutwertfunktionen in C keine konstanten Eingaben?yes
const
ist hier überflüssig, was stellst du dir vor?– MM
13. Dezember 2019 um 4:48 Uhr
@MM Ich gehe davon aus, dass es zu einem Kompilierzeitfehler kommen würde, wenn ich versuchen würde, den Wert der Eingabe innerhalb der Funktion zu ändern. Ist das falsch?
– Benutzer24205
13. Dezember 2019 um 5:05 Uhr
Da der Parameter innerhalb der Funktion eine lokale Kopie ist, fügt das Hinzufügen von
const
ist völlig bedeutungslos.– Ludin
13. Dezember 2019 um 9:35 Uhr
“fabsf ändert den Wert der Eingabe nicht, oder?” Woher wissen Sie das? Der Parameter wird als Wert übergeben.
– David Schwartz
14. Dezember 2019 um 18:43 Uhr
Der folgende Code ist legal C:
float const x = -1.0; float y = fabsf(x);
so kommt es mir vorfabsf
tut konstante Eingaben akzeptieren. Es gibt keine Möglichkeit zu sagen: „Du kannst mir eins reichenfloat
nach Wert, aber Sie können a nicht übergebenconst float
.” (Und wie wir in den Antworten sehen, bietet C keine Möglichkeit dazu benötigen dass die Eingabe einer Funktion a istfloat const
.)– David K
14. Dezember 2019 um 21:55 Uhr