Warum akzeptieren die Absolutwertfunktionen in C keine konstanten Eingaben?

Lesezeit: 5 Minuten

Benutzer-Avatar
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 fabsf tut 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


Benutzer-Avatar
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.

Benutzer-Avatar
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:

float correct(float const value);

float erroneous(float const value);

float changer(float value);

float correct(float value) {
  return -value;
}

float erroneous(float value) {
  value = -value;
  return value;
}

float changer(float value) {
    value = -value;
    return value;
}

Es gibt keine Fehlermeldung.

Wie auch immer, ich werde das Original an Ort und Stelle lassen, in der Hoffnung, dass es helfen könnte.


Original

Das const an einem Parameter macht dies Parameter schreibgeschützt innerhalb der Funktion.

Zum Beispiel:

float correct(float const value) {
  return -value;
}

float erroneous(float const value) {
  value = -value;
  return value;
}

float changer(float value) {
  value = -value;
  return value;
}

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!

void effective(int const * pointer);

void futile(int * const pointer);

void possible_but_overly_restricted(int const * const pointer);

  • 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


Benutzer-Avatar
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.

1311650cookie-checkWarum akzeptieren die Absolutwertfunktionen in C keine konstanten Eingaben?

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

Privacy policy