Forum: PC-Programmierung Probleme mit Struktur und Pointer


von jens (Gast)


Lesenswert?

Hi, Microsoft Visual Studio C++ zeigt mir hier immer wieder folgende 
Fehlermeldungen an:

test.cpp(23) : error C2440: 'Initialisierung': 'void *' kann nicht in 
'PTData' konvertiert werden

test.cpp(30) : error C2440: 'Typumwandlung': 'void *' kann nicht in 
'PTData' konvertiert werden
1
typedef struct
2
{
3
  unsigned char ucValue1;
4
  unsigned char ucValue2;
5
}TData, PTData;
6
7
int _tmain(int argc, _TCHAR* argv[])
8
{
9
...
10
PTData ptrdata = (void*)0;
11
ptrdata = (PTData)MemPool_Get(&data);
12
}

Was kann ich da tun? Hab ich möglicherweise irgendwo einen heftigen 
Fehler gemacht?

von jens (Gast)


Lesenswert?

Hab die Struktur falsch gepostet. Hier die richtige Definition.
1
typedef struct
2
{
3
  unsigned char ucValue1;
4
  unsigned char ucValue2;
5
}TData, *PTData;

von Joachim (Gast)


Lesenswert?

Hallo

Könnte es damit zusammemhängen??

PTData ptrdata = (void*)0;

Gruß
Joachim

von Flo (Gast)


Lesenswert?

PTData *ptrdata = (void*)0;
       ^^
Zeiger?

von Rolf Magnus (Gast)


Lesenswert?

> Was kann ich da tun?

Angeben, ob du das als C oder als C++ übersetzt, und die Zeilen, auf die 
sich die Fehlermeldungen beziehen, markieren. Eine Zeile 23 und eine 
Zeile 30 gibt es in deinem Code nicht.

Ich nehme mal an, daß es als C++ übersetzt wird und eine der 
Fehlermeldungen sich auf diese Zeile bezieht:
1
PTData ptrdata = (void*)0;

Zur anderen Fehlermeldung finde ich keine passende Zeile.

In C++ kann man einen void* nicht implizit in einen anderen Zeiger 
konvertieren. Warum castest du überhaupt die 0? Ohne den Cast sollte das 
gehen.

Übrigens: Du solltest dir abgewöhnen, Zeiger hinter irgendwelchen 
typedef-Namen zu verstecken. Also statt PTData lieber ein TData*. Da 
sieht man auf den ersten Blick, daß es ein Zeiger ist.

von Karl H. (kbuchegg)


Lesenswert?

Und anstatt der 0 sollte man sich angewöhnen das vordefinierte Makro 
NULL zu benutzen. Denn dann sieht man ebenfalls, dass es sich um etwas 
handelt, was mit Pointern zu tun hat.

NULL
0
'\0'

ist im Grunde alles dasselbe. Und trotzdem ist man gut beraten je nach 
Kontext die Version zu nehmen, die angemessen ist.

von Rolf Magnus (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Und anstatt der 0 sollte man sich angewöhnen das vordefinierte Makro
> NULL zu benutzen. Denn dann sieht man ebenfalls, dass es sich um etwas
> handelt, was mit Pointern zu tun hat.

In C++ wird meistens eher empfohlen 0 statt NULL zu verwenden, da es 
dort eh keinen Unterschied macht und manchmal irreführend ist. Beispiel:
1
void foo(int i);
2
void foo(char* c);
3
4
// ...
5
6
foo(NULL);  // ruft foo(int) mit dem Wert 0 auf.

> NULL
> 0
> '\0'
>
> ist im Grunde alles dasselbe.

In C kann NULL auch als (void*)0 definiert sein. In C++ nicht.

> Und trotzdem ist man gut beraten je nach Kontext die Version zu nehmen,
> die angemessen ist.

Bei C++0x wird's dafür extra ein neues Schlüsselwort 'nullptr' geben, 
das zwar in beliebigen Pointer-Kontexten verwendet werden kann, aber 
nicht als Integer.

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:

> Bei C++0x wird's dafür extra ein neues Schlüsselwort 'nullptr' geben,
> das zwar in beliebigen Pointer-Kontexten verwendet werden kann, aber
> nicht als Integer.

Endlich mal etwas, bei dem das Gremium reagiert hat.
Wenn man sie jetzt noch dazu bringen könnte, die Semantik von 'virtual' 
ein bischen zu ändern :-)

von Rolf Magnus (Gast)


Lesenswert?

Was meinst du damit?

von Karl H. (kbuchegg)


Lesenswert?

In abgeleiteten Klassen ist das Schlüsselwort virtual 'optional'

Wenn du gezwungen bist, in einer Klasse eine Funktion virtual zu machen 
oder das virtual rauszunehmen, ändert sich die Semantik auch für 
abgeleitete Klassen. C++ hat keinen Mechanismus der einen zwingt, diese 
Fälle anzusehen

C# hat das in meinen Augen richtig gemacht.
Die 'erste' Funktion in der Ableitungshierarchie wird 'volatile' 
markiert, in den abgeleiteten Klassen heisst es dann 'override'

Sobald du damit in der Hierarchie irgendetwas änderst (ändern musst) 
klopft dir der Compiler auf die Finger:

   Existiert in der Basisklasse eine virtual Funktion und habe ich
   in der abgeleiteten Klasse dieselbe Funktion als nicht override,
   ist das ein Fehler.

   Ist in einer Klasse ein Member 'override', dann muss es in einer
   der vorhergehenden Basisklasse ein virtual dazu geben.

-> bin ich gezwungen in einer Basisklasse ein virtual nachzurüsten
   oder zu entfernen, dann zeigt mir der Compiler alle anderen Klassen,
   in denen sich das auswirken wird und ich kann mir das ansehen,
   was die Auswirkungen sein werden.

Bei größeren Projekten ist es zur Zeit in C++ extrem gefährlich ein 
virtual nachzurüsten, weil ich nicht mehr überblicke auf welche anderen 
Klassen sich das noch auswirken wird.

von Rolf Magnus (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> In abgeleiteten Klassen ist das Schlüsselwort virtual 'optional'

Ok, stimmt. Das ist nicht ideal. Mir ist aber nicht bekannt, daß das 
geändert würde. Was bei C++0x im Vordergrund steht, ist immer, daß man 
möglichst wenig neue Schlüsselwörter einfügt und daß die alte Syntax 
weiter gültig bleibt, damit man bestehende Programme nicht ändern muß, 
um sie mit einem C++0x-Compiler übersetzt zu bekommen. Das schänkt 
natürlich immer etwas ein.

> Bei größeren Projekten ist es zur Zeit in C++ extrem gefährlich ein
> virtual nachzurüsten, weil ich nicht mehr überblicke auf welche anderen
> Klassen sich das noch auswirken wird.

Dazu hat man ja Doxygen ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.