Thread View: de.comp.lang.c++
7 messages
7 total messages
Started by Ullrich von Bassewitz
Wed, 06 Dec 1995 16:38
Typ eines ?: Ausdruck?
Author: Ullrich von Bassewitz
Date: Wed, 06 Dec 1995 16:38
Date: Wed, 06 Dec 1995 16:38
32 lines
1389 bytes
1389 bytes
Und gleich nochmal eine Frage:
Welchen Typ hat das Ergebnis eines ?: Ausdrucks?
Grund fuer meine Frage ist wiederum ein Verhalten der neuen Version von gcc.
Und zwar wird ploetzlich ein Konstrukt wie
Window* W = (A == B)? LastWindow : NULL;
mit einer Warnung kommentiert:
"ANSI C++ forbids implicit conversion from `void*' in initialization"
Was g++ da macht ist so ungefaehr klar: Der ?: Ausdruck wird ausgewertet,
das Ergebnis ist aber kein Window* (so wie frueher und bei allen anderen
Compilern die ich kenne), sondern es wird "void*" als kleinster gemeinsamer
Nenner gewaehlt, woraufhin die Zuweisung fehlschlaegt.
Ist das tatsaechlich nach dem neuen Standard richtig?
Wenn ich den ?: Ausdruck als andere Schreibweise fuer ein if ansehe, dann
ist es nicht richtig (if Ausdruecke werden von g++ auch korrekt gehandhabt),
andererseits hat ein if Statement auch keinen Ergebnistyp...
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Re: Typ eines ?: Ausdruck?
Author: Dietmar Kuehl
Date: Wed, 06 Dec 1995 19:54
Date: Wed, 06 Dec 1995 19:54
47 lines
2859 bytes
2859 bytes
Hi, Ullrich von Bassewitz (uz@wuschel.ibb.schwaben.com) wrote: : Welchen Typ hat das Ergebnis eines ?: Ausdrucks? Kommt drauf an... :-) Die Section, ueber den '?:' Operator ist relativ ausfuehrlich. Auf jeden Fall laeuft es immer wieder darauf hinaus, dass Typkonversionen angewendet werden, so dass der Typ vom 2. und vom 3. Operand identisch ist. Fuer Pointer bedeuted dies (September DWP 5.15 [expr.cond] Vers 3): "... Otherwise, if both the second and the third expressions are either a pointer or a null pointer constant, pointer conversions (_conv.ptr_) are performed to bring them to a common type, which shall be a cv-qualified or cv-unqualified version of the type of either the second or the third expression. ...". : Grund fuer meine Frage ist wiederum ein Verhalten der neuen Version von gcc. : Und zwar wird ploetzlich ein Konstrukt wie : Window* W = (A == B)? LastWindow : NULL; : mit einer Warnung kommentiert: : "ANSI C++ forbids implicit conversion from `void*' in initialization" Der Trick liegt daran, dass 'NULL' beim gcc als '(void*)0' definiert ist. Das ist nach DWP 18.1 (lib.support.types) [Fussnote 135 im April DWP] nicht zulaessig: "Possible definitions inlucde 0 and 0L, but not (void*)0". : Was g++ da macht ist so ungefaehr klar: Der ?: Ausdruck wird ausgewertet, : das Ergebnis ist aber kein Window* (so wie frueher und bei allen anderen : Compilern die ich kenne), sondern es wird "void*" als kleinster gemeinsamer : Nenner gewaehlt, woraufhin die Zuweisung fehlschlaegt. : Ist das tatsaechlich nach dem neuen Standard richtig? Die Konversion, die der gcc in diesem Fall macht ja, die Definition von 'NULL' nicht. Der Fehler wird am Einfachst dadurch behoben, dass man anstelle von 'NULL' einfach '0' verwendet. Am Anfang musste ich mich auch daran gewoehnen (ich habe lange C programmiert, bevor ich auf C++ umgestiegen bin), aber inzwischen finde ich 'NULL' ziemlich haesslich. BTW, gcc ist nicht der einzige Compiler (vielmehr libg++ nicht die einzige Library), der das Problem hat. Das gibt es mit anderen Compilern auch. Daher loesst die '0' das Problem in portabler weise; man gewinnt, IMHO, durch 'NULL' nichts. -- dietmar.kuehl@uni-konstanz.de http://www.informatik.uni-konstanz.de/~kuehl I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Typ eines ?: Ausdruck?
Author: Uwe Tantz
Date: Wed, 06 Dec 1995 20:23
Date: Wed, 06 Dec 1995 20:23
47 lines
2648 bytes
2648 bytes
On 6 Dec 1995, Ullrich von Bassewitz wrote: > Und gleich nochmal eine Frage: > > Welchen Typ hat das Ergebnis eines ?: Ausdrucks? > > Grund fuer meine Frage ist wiederum ein Verhalten der neuen Version von gcc. > Und zwar wird ploetzlich ein Konstrukt wie > > Window* W = (A == B)? LastWindow : NULL; > > mit einer Warnung kommentiert: > "ANSI C++ forbids implicit conversion from `void*' in initialization" > > Was g++ da macht ist so ungefaehr klar: Der ?: Ausdruck wird ausgewertet, > das Ergebnis ist aber kein Window* (so wie frueher und bei allen anderen > Compilern die ich kenne), sondern es wird "void*" als kleinster gemeinsamer > Nenner gewaehlt, woraufhin die Zuweisung fehlschlaegt. > > Ist das tatsaechlich nach dem neuen Standard richtig? > > Wenn ich den ?: Ausdruck als andere Schreibweise fuer ein if ansehe, dann > ist es nicht richtig (if Ausdruecke werden von g++ auch korrekt gehandhabt), > andererseits hat ein if Statement auch keinen Ergebnistyp... > > Gruss > > Ich weiss zwar nicht, was der Standard zu diesem Thema sagt, ich habe aber beim (nicht mehr ganz) aktuellen Microsoft Visual C++ 2.2 das gleiche Problem: Der Typ des ?:-operators muss sowohl mit dem zweiten, als auch mit dem dritten Argument vertraeglich sein, also exakt das gleiche Verhalten wie beim gnu. Ich hab mir dann damit beholfen den NULL Pointer auf den passenden Typ zu casten (auf Window* in deinem Bsp.). Soweit ich's ueberblicke, macht das aber nur im Zusammenhang mit dem NULL-Pointer Probleme, weil bei der Zuweisung von NULL die Typsicherheit gewissermassen aufgehoben ist (NULL ist ja als #define NULL 0L implementiert). Tschuess Uwe +---------------------+-------------------------------------------+ | Uwe-Krischna Tantz | Tel: 0941 / 56 31 40 | | Blaue-Stern-Gasse 7a| EMail: uwe.tantz@physik.uni-regensburg.de | | 93047 Regensburg | | +---------------------+-------------------------------------------+
Re: Typ eines ?: Ausdruck?
Author: Ullrich von Bassewitz
Date: Thu, 07 Dec 1995 12:19
Date: Thu, 07 Dec 1995 12:19
37 lines
1666 bytes
1666 bytes
Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote:
> Der Trick liegt daran, dass 'NULL' beim gcc als '(void*)0' definiert
> ist. Das ist nach DWP 18.1 (lib.support.types) [Fussnote 135 im April
> DWP] nicht zulaessig: "Possible definitions inlucde 0 and 0L, but not
> (void*)0".
Das ist falsch und wuerde auch ueberhaupt nicht funktionieren, da in C++
eine Konvertierung von void* in einen anderen Zeigertyp (im Gegensatz zu C)
nicht automatisch durchgefuehrt wird.
Das hier ist aus /usr/include/stdio.h:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL (void*)0
#endif
#endif
> Die Konversion, die der gcc in diesem Fall macht ja, die Definition von
> 'NULL' nicht. Der Fehler wird am Einfachst dadurch behoben, dass man
> anstelle von 'NULL' einfach '0' verwendet. Am Anfang musste ich mich
> auch daran gewoehnen (ich habe lange C programmiert, bevor ich auf C++
> umgestiegen bin), aber inzwischen finde ich 'NULL' ziemlich haesslich.
Das scheint auf jeden Fall nicht die Antwort zu sein, weil Deine Annahme
(NULL == (void*)0) falsch ist.
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Re: Typ eines ?: Ausdruck?
Author: Ullrich von Bassewitz
Date: Thu, 07 Dec 1995 12:26
Date: Thu, 07 Dec 1995 12:26
28 lines
1842 bytes
1842 bytes
Uwe Tantz (c4037@rphc1.physik.uni-regensburg.de) wrote:
> Ich weiss zwar nicht, was der Standard zu diesem Thema sagt, ich habe
> aber beim (nicht mehr ganz) aktuellen Microsoft Visual C++ 2.2 das
> gleiche Problem: Der Typ des ?:-operators muss sowohl mit dem zweiten,
> als auch mit dem dritten Argument vertraeglich sein, also exakt das
> gleiche Verhalten wie beim gnu.
> Ich hab mir dann damit beholfen den NULL Pointer auf den passenden Typ zu
> casten (auf Window* in deinem Bsp.).
So habe ich mir auch geholfen. Was mich interessieren wuerde ist, ob es sich
hier um eine Anforderung des neuen ANSI Standards fuer C++ handelt (dann
waere es ja ok), oder um eine Eigenheit der Version 2.7. von g++. Sowohl
Borland-C++ fuer DOS & OS/2, als auch Watcom auf allen Plattformen und die
GNU Compiler bis hin zu Version 2.6.3 hatten naemlich keinerlei Probleme mit
diesem Konstrukt. Wenn der Ergebnistyp tatsaechlich void* waere, dann
muesste eigentlich nicht nur eine Warnung, sondern eine Fehlermeldung
ausgegeben werden, da void* (in C++) nicht zuweisungskompatibel zu einem
typisierten Zeiger ist. Daraus wuerde ich jetzt mal folgern, dass die
anderen Compiler den ?: Ausdruck nicht mit void* als Ergebnistyp evaluieren.
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Re: Typ eines ?: Ausdruck?
Author: Dietmar Kuehl
Date: Thu, 07 Dec 1995 23:44
Date: Thu, 07 Dec 1995 23:44
125 lines
4859 bytes
4859 bytes
Hi, Ullrich von Bassewitz (uz@wuschel.ibb.schwaben.com) wrote: : Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote: : > Der Trick liegt daran, dass 'NULL' beim gcc als '(void*)0' definiert : > ist. Das ist nach DWP 18.1 (lib.support.types) [Fussnote 135 im April : > DWP] nicht zulaessig: "Possible definitions inlucde 0 and 0L, but not : > (void*)0". : Das ist falsch und wuerde auch ueberhaupt nicht funktionieren, da in C++ : eine Konvertierung von void* in einen anderen Zeigertyp (im Gegensatz zu C) : nicht automatisch durchgefuehrt wird. Es ist korrekt, dass es nicht funktionieren wuerde. Es funktioniert ja auch nicht :-) ... nur um die Aussage "das ist falsch" mal in Frage zu stellen: Wie hast Du rausgefunden, das 'NULL' nicht '((void*)0)' ist, wenn man den gcc verwendet? Ich habe es mit dem Compiler gemacht, indem ich nur den Praeprozessorschritt habe machen lassen und mir angeguckt habe, zu was 'NULL' denn gerade definiert ist. Das (ueberraschende; das hatte ich naemlich wirklich nicht erwartet) Ergebnis, wenn man sich das fuer ALLE Headerfiles anguckt, ist, dass 'NULL' in libg++-2.7.1 NICHT konsistent definiert ist. Hier ist eine Liste der Header (mit ihren ANSI/ISO Namen) und wie 'NULL' definiert ist. Wenn in der Liste 'NULL' steht, so wurde entweder 'NULL' nicht definiert oder es gibt kein Headerfile in libg++ was ungefaehr dem entsprechenden ANSI/ISO Header entspricht: algorithm: ((void *)0) bitset: NULL complex: ( 0) deque: ((void *)0) exception: NULL fstream: ((void*)0) functional: NULL iomanip: ((void*)0) ios: ((void*)0) iosfwd: ((void*)0) iostream: ((void*)0) istream: ((void*)0) iterator: ((void *)0) limits: NULL list: ((void *)0) locale: NULL map: ((void *)0) memory: ((void *)0) new: ((void *)0) numeric: ((void *)0) ostream: ((void*)0) queue: NULL set: ((void *)0) sstream: NULL stack: NULL stdexcept: NULL streambuf: ((void*)0) string: ((void *)0) typeinfo: NULL utility: NULL valarray: NULL vector: ((void *)0) cassert: NULL cctype: NULL cerrno: NULL cfloat: NULL ciso646: NULL climits: NULL clocale: 0 cmath: ( 0) csetjmp: NULL csignal: 0 cstdarg: NULL cstddef: ((void *)0) cstdio: ( 0) cstdlib: 0 cstring: 0 ctime: 0 cwchar: ((void *)0) cwctype: ( 0) Diese Liste habe ich automatisch erstellen lassen, indem ich folgendes C++ Programm Preprocessed habe (mit g++ -E tst.cc): #include <headername> NULL Dabei wurde 'headername' mittels sed auf den jeweils entsprechenden Namen in libg++-2.7.1 gesetzt. : Das hier ist aus /usr/include/stdio.h: 'stdio.h' ist eins von 50 Standard Header, die es in ANSI/ISO gibt. Warum sollte ausgerechnet die Definition aus 'stdio.h' genommen werden? : #ifndef NULL : #ifdef __cplusplus : #define NULL 0 : #else : #define NULL (void*)0 : #endif : #endif Das deckt sich zwar nicht mit dem Ergebnis, was ich fuer stdio.h gefunden habe '( 0)', aber es kann sein, dass die Definition in stdio.h (ANSI/ISO Name ist uebrigens '<cstdio>') aus einen Headerfile stammt, dass von stdio.h included wurde. : > Die Konversion, die der gcc in diesem Fall macht ja, die Definition von : > 'NULL' nicht. Der Fehler wird am Einfachst dadurch behoben, dass man : > anstelle von 'NULL' einfach '0' verwendet. Am Anfang musste ich mich : > auch daran gewoehnen (ich habe lange C programmiert, bevor ich auf C++ : > umgestiegen bin), aber inzwischen finde ich 'NULL' ziemlich haesslich. : Das scheint auf jeden Fall nicht die Antwort zu sein, weil Deine Annahme : (NULL == (void*)0) falsch ist. Ich will mich nicht auf einen Streiterei einlassen, behaupte aber, insbesondere mit Ruecksicht auf die oben angefuehrten Argumente, dass meine Erklaerung korrekt ist. Solange wie nicht jemand eine andere, schluessige Erklaerung liefert, werde ich mich auch von Behauptungen, die das Problem nicht unbedingt beeinflussen, etwa dass 'NULL' doch in 'stdio.h' richtig definiert wird, nicht beirren lassen. -- dietmar.kuehl@uni-konstanz.de http://www.informatik.uni-konstanz.de/~kuehl I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Typ eines ?: Ausdruck?
Author: Ullrich von Bassewitz
Date: Fri, 08 Dec 1995 17:06
Date: Fri, 08 Dec 1995 17:06
58 lines
2955 bytes
2955 bytes
Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote:
> Ullrich von Bassewitz (uz@wuschel.ibb.schwaben.com) wrote:
> : Das ist falsch und wuerde auch ueberhaupt nicht funktionieren, da in C++
> : eine Konvertierung von void* in einen anderen Zeigertyp (im Gegensatz zu C)
> : nicht automatisch durchgefuehrt wird.
>
> Es ist korrekt, dass es nicht funktionieren wuerde. Es funktioniert ja
> auch nicht :-) ... nur um die Aussage "das ist falsch" mal in Frage zu
> stellen: Wie hast Du rausgefunden, das 'NULL' nicht '((void*)0)' ist,
> wenn man den gcc verwendet? Ich habe es mit dem Compiler gemacht,
Das ist viel zu viel Aufwand :-)
In C++ ist ein void Zeiger nicht zuweisungskompatibel zu einem typisierten
Zeiger (wie in C). D.h. das Statement
char* S = malloc (100);
erzeugt immer eine Fehlermeldung des Compilers, weil er nicht implizit das
Ergebnis von malloc (void*) nach char* castet.
Aus dem Grund _kann_ NULL ueberhaupt nicht als (void*)0 definiert sein, weil
das unter C++ nicht funktionieren wuerde!
Das zeigt auch mein Zitat aus stdio.h, dort ist NULL fuer g++ und fuer gcc
verschieden definiert.
Deine Aussage bezueglich der Definition von NULL kann insofern stimmen, als
g++ (zumindest die Version die ich hier habe) einen Bug hat, was das angeht:
char* S = (void*)0;
Wird auch mit -Wall ohne zu meckern uebersetzt. Dagegen wird
void* X = 0;
char* S = X;
mit einer Warnung bedacht ("ANSI-C++ forbids implicit conversion..."). Das
zweite Beispiel zeigt dabei, dass beim ersten eigentlich auch eine Warnung
kommen sollte, der Text der Warnung ("ANSI-C++ forbids...") zeigt, dass dies
eigentlich ein Fehler und keine Warnung sein sollte. Ich vermute mal, dass
der Sinn davon ist, moeglichst viel alten Code am Laufen zu halten, auch
solchen, der NULL selber definiert und keine Header-Files einbindet.
Andere Compiler brechen hier tataechlich mit einem Fehler ab.
Wo Du recht hast und was ich probieren koennte, ist anstatt von NULL 0 zu
verwenden. Wenn das das Problem loesen sollte, dann wird die Geschichte aber
eher zweifelhafter, weil es ja wohl kaum richtig sein kann, wenn der Ersatz
von 0 in einem Zeiger-Kontext durch NULL ploetzlich Warnungen produziert.
Das sollte nicht der Sinn von NULL sein (siehe C-FAQ).
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads