
Nefarel NefX
Betrachten Sie folgenden Code:
void foo(unsigned int x)
{
}
int main()
{
foo(-5);
return 0;
}
Dieser Code lässt sich ohne Probleme kompilieren. Fehler wie dieser können viele Probleme verursachen und sind schwer zu finden. Warum erlaubt C++ eine solche Konvertierung?

Markus B
Die kurze Antwort lautet, weil C solche Konvertierungen ursprünglich unterstützte und sie vorhandene Software in C++ nicht beschädigen wollten.
Beachten Sie, dass einige Compiler davor warnen. Zum Beispiel g++ -Wconversion
wird vor diesem Konstrukt warnen.
In vielen Fällen ist die implizite Konvertierung sinnvoll, zum Beispiel wenn int
wurde in Berechnungen verwendet, aber das Endergebnis wird niemals negativ sein (aus dem Algorithmus bekannt und optional geltend gemacht).
BEARBEITEN: Zusätzliche wahrscheinliche Erklärung: Denken Sie daran, dass C ursprünglich eine viel lockerer typisierte Sprache war als C++ jetzt. Mit Funktionsdeklarationen im K&R-Stil hätte der Compiler keine Möglichkeit gehabt, solche impliziten Konvertierungen zu erkennen, also warum sich die Mühe machen, sie in der Sprache einzuschränken. Ihr Code würde zum Beispiel ungefähr so aussehen:
int foo(x)
unsigned int x
{
}
int main()
{
foo(-5);
return 0;
}
während die Erklärung allein gewesen wäre int foo(x);
Der Compiler verließ sich tatsächlich darauf, dass der Programmierer die richtigen Typen in jeden Funktionsaufruf übergab, und führte keine Konvertierungen durch am Aufrufort. Wenn die Funktion dann tatsächlich aufgerufen wurde, wurden die Daten auf dem Stack (usw.) so interpretiert, wie die Funktionsdeklaration angegeben ist.
Sobald Code geschrieben wurde, der sich auf diese Art der impliziten Konvertierung stützte, wäre es viel schwieriger geworden, ihn aus ANSI C zu entfernen, selbst wenn Funktionsprototypen mit tatsächlichen Typinformationen hinzugefügt wurden. Dies ist wahrscheinlich der Grund, warum es auch jetzt noch in C bleibt. Dann kam C++ und entschied sich erneut dafür, die Abwärtskompatibilität mit C nicht zu brechen und solche impliziten Konvertierungen weiterhin zuzulassen.
- Nur eine weitere Eigenart einer Sprache, die viele dumme Eigenarten hat.
- Die Konvertierung ist gut definiert, um sie zu umschließen, was in einigen Fällen nützlich sein kann.
- Es ist abwärtskompatibel mit C, was dies aus den oben genannten Gründen tut.
Treffen Sie Ihre Wahl.

j4x
@ user168715 hat recht. C++ wurde ursprünglich als Obermenge von C, vorgeben, so abwärtskompatibel wie möglich zu sein. Die “C”-Philosophie besteht darin, die meiste Verantwortung dem Programmierer zu übertragen, anstatt gefährliche Dinge zu verbieten. Für C-Programmierer ist es der Himmel, für Java-Programmierer die Hölle… Geschmackssache.
Ich werde die Standards ausgraben, um zu sehen, wo genau es geschrieben steht, aber ich habe im Moment keine Zeit dafür. Ich werde meine Antwort so schnell wie möglich bearbeiten.
Ich stimme auch zu, dass ein Teil der geerbten Freiheit zu Fehlern führen kann, die wirklich schwer zu debuggen sind, also füge ich dem Gesagten hinzu, dass Sie in g ++ eine Warnung aktivieren können, um Sie vor dieser Art von Fehlern zu bewahren: -Wconversion
Flagge.
-W-Konvertierung
Warnung vor impliziten Konvertierungen, die einen Wert ändern können. Dazu gehören Konvertierungen zwischen Real und Integer, wie abs (x), wenn x doppelt ist; Konvertierungen zwischen signiert und unsigned, wie unsigned ui = -1; und Konvertierungen in kleinere Typen wie sqrtf (M_PI). Warnen Sie nicht bei expliziten Umwandlungen wie abs ((int) x) und ui = (unsigned) -1 oder wenn der Wert durch die Konvertierung nicht geändert wird, wie in abs (2.0). Warnungen zu Konvertierungen zwischen vorzeichenbehafteten und vorzeichenlosen Ganzzahlen können mit -Wno-sign-conversion deaktiviert werden.
Für C++ warnen Sie auch vor verwirrender Überladungsauflösung für benutzerdefinierte Konvertierungen; und Konvertierungen, die niemals einen Typkonvertierungsoperator verwenden: Konvertierungen in void, denselben Typ, eine Basisklasse oder einen Verweis darauf. Warnungen zu Konvertierungen zwischen vorzeichenbehafteten und vorzeichenlosen Ganzzahlen sind in C++ standardmäßig deaktiviert, es sei denn, -Wsign-conversion ist explizit aktiviert.
Andere Compiler können ähnliche Flags haben.
Zur Zeit des ursprünglichen C-Standards wurde die Konvertierung bereits von vielen (allen?) Compilern erlaubt. Basierend auf dem C-Grundprinzip scheint es wenig (wenn überhaupt) Diskussionen darüber gegeben zu haben, ob solche impliziten Konvertierungen erlaubt sein sollten. Als C++ auf den Markt kam, waren solche impliziten Konvertierungen so weit verbreitet, dass ihre Beseitigung die Sprache mit einem Großteil des C-Codes inkompatibel gemacht hätte. Es würde wahrscheinlich haben C++ sauberer gemacht; es würde sicherlich haben es viel seltener verwendet — bis zu dem Punkt, dass es wahrscheinlich nie über die Stufe “C mit Klassen” hinausgekommen wäre, und selbst das wäre nur eine meist ignorierte Fußnote in der Geschichte der Bell-Labore.
Die einzige wirkliche Frage in dieser Richtung war zwischen den Regeln “Werterhaltung” und “Vorzeichenerhaltung ohne Vorzeichen” bei der Förderung von unsignierten Werten, die “kleiner” als int sind. Der Unterschied zwischen den beiden entsteht, wenn (zum Beispiel) ein unsigned short zu einem unsigned char hinzugefügt wird.
Unsigned Preserving Rules besagen, dass Sie beide zu unsigned int hochstufen. Werterhaltende Regeln besagen, dass Sie beide Werte fördern int
, wenn es kann alle Werte des ursprünglichen Typs darstellen (z. B. den üblichen Fall von 8-Bit-Char, 16-Bit-Short und 32-Bit-Int). Auf der anderen Seite, wenn int und short beide 16 Bit sind, also int nicht alle Werte von unsigned short darstellen kann, dann stufen Sie unsigned short zu unsigned int hoch (beachten Sie, dass es immer noch als Promotion betrachtet wird, obwohl es nur passiert, wenn es wirklich so ist nicht eine Werbeaktion — dh die beiden Typen haben die gleiche Größe).
Auf Gedeih und Verderb (und es wurde oft in beide Richtungen argumentiert) entschied sich das Komitee für werterhaltende und nicht für unsignierte erhaltende Beförderungen. Beachten Sie jedoch, dass es sich hierbei um eine Konvertierung in die entgegengesetzte Richtung handelt: Statt von signiert nach unsigniert geht es darum, ob Sie unsigniert in signiert konvertieren.
Denn der Standard erlaubt eine implizite Konvertierung von signed
zu unsigned
Typen.
Ebenfalls (int)a + (unsigned)b
Ergebnisse zu unsigned
– Dies ist ein C++-Standard.
10188600cookie-checkWarum erlaubt C++ die implizite Konvertierung von int zu unsigned int?yes
Banale Antwort: weil C++ so konzipiert wurde, dass es (größtenteils) abwärtskompatibel mit C ist, und C implizite Umwandlungen zwischen ganzzahligen Typen erlaubt.
– Benutzer168715
10. März 2011 um 17:20 Uhr
Interessanterweise warnen die meisten Compiler, wenn Sie vergleichen
int
mitunsigned int
wie ini < ui
– Nawaz
10. März 2011 um 17:21 Uhr
@ user168715: das ergibt keinen Sinn. Warnung bedeutet nicht, dass es Ihnen nicht erlaubt ist. Es bedeutet lediglich, dass es ein Problem bei der impliziten Konvertierung geben könnte!
– Nawaz
10. März 2011 um 17:22 Uhr
@Nawaz: Die Frage ist “Warum [does] C++ erlaubt eine solche Konvertierung“; „Warnung“ erscheint nirgendwo im Originaltitel oder in der Frage.
– Benutzer168715
10. März 2011 um 17:29 Uhr
Leute, Nawaz hat eine interessante Beobachtung gemacht, keinen Erklärungsversuch. Kühlen Sie Ihre Jets.
– Matt K
10. März 2011 um 17:36 Uhr