🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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?
#963
Author: Ullrich von Bassewitz
Date: Wed, 06 Dec 1995 16:38
32 lines
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?
#968
Author: Dietmar Kuehl
Date: Wed, 06 Dec 1995 19:54
47 lines
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?
#966
Author: Uwe Tantz
Date: Wed, 06 Dec 1995 20:23
47 lines
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?
#971
Author: Ullrich von Bassewitz
Date: Thu, 07 Dec 1995 12:19
37 lines
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?
#972
Author: Ullrich von Bassewitz
Date: Thu, 07 Dec 1995 12:26
28 lines
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?
#977
Author: Dietmar Kuehl
Date: Thu, 07 Dec 1995 23:44
125 lines
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?
#982
Author: Ullrich von Bassewitz
Date: Fri, 08 Dec 1995 17:06
58 lines
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