Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

14.11.2010, 13:39

LPCWSTR kopieren

Hi,
ich habe ein Problem mit den LPCWSTR-Pointern, ich glaube das bedeutet so viel , wie "wchar_t*".

Wenn ich mit wcscpy() versuche den String zu kopieren, etwa so:

C-/C++-Quelltext

1
2
3
4
LPCWSTR String1 = (L"Hallo");
LPCWSTR String2 = NULL;

wcscpy(String1, String2);


wird der zweite Parameter übernommen, aber beim ersten gibts einen Fehler.

Wenn ich den ersten Parameter mit (WCHAR*) oder (wchar_t*) caste, bekomme ich beim starten einen Speicherfehler.

Danke schon mal,

Diddus

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

2

14.11.2010, 13:42

Jo, immer schoen auf unitialisierte Variablen zugreifen, dann hat man immer was zu fragen, warum das Programm "irgednwas" macht...

GR-PA

Treue Seele

Beiträge: 326

Wohnort: Daheim

Beruf: Faulenzer

  • Private Nachricht senden

3

14.11.2010, 17:41

Die lange, erklärende und hilfreichere Version von TGGCs Post (und die korrektere denn er initialisiert schließlich seine Variablen...):

Du hast gleich mehrere Denkfehler.
LPCWSTR steht für "long pointer [to a] constant wide string". Es entspricht also const wchar_t*.

C-Strings sind Arrays von Zeichen, also (w)char(_t)[]. Das ist ja auch irgendwie logisch, denn diese Zeichen müssen ja auch irgendwo gespeichert werden.

In deinem Code erstellst du die Zeichenkette L"Hallo" (ein konstantes Feld mit den Werten 'H', 'a', 'l', 'l', 'o', 0). Dein wchar_t* String1, dem du das zuweist zeigt jetzt also auf das erste Element des Feldes.
Das man nur Zeiger auf Felder verwendet ist auch der Grund, warum C-Strings überhaupt mit Funktionen wie wcscpy kopiert werden müssen, und warum s1 = s2 nicht funktioniert (zumindest nicht so wie man annehmen könnte).
Wenn du dieses Feld in ein anderes kopieren willst, dann muss in dem anderen Feld natürlich auch genug Platz für die 6 Zeichen des ersten Feldes sein.

wcscpy ist (in VC++ 2010) so definiert: (mit ein paar ergänzenden Kommentaren meinerseits)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/***
*wchar_t *wcscpy(dst, src) - copy one wchar_t string over another
*
*Purpose:
*       Copies the wchar_t string src into the spot specified by
*       dest; assumes enough room. <---- WICHTIG
*
*Entry:
*       wchar_t * dst - wchar_t string over which "src" is to be copied
*       const wchar_t * src - wchar_t string to be copied over "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*******************************************************************************/

wchar_t * __cdecl wcscpy(wchar_t * dst, const wchar_t * src)
{
        wchar_t * cp = dst;

        while( *cp++ = *src++ ) // Zeigerarithmetik: ++ "schiebt" den Zeiger um sizeof(wchar_t) Bytes "weiter".
                ;               /* Copy src over dst */

        return( dst );
}


Daraus erkennt man folgendes:
1. Der erste Parameter gibt das Ziel an und nicht, wie von dir angenommen, der zweite.
2. Die Funktion ist eigentlich ganz simpel: Die beiden Felder werden durchgegangen, bis die abschließende 0 des Ausgansgfeldes erreicht wurde. Dabei wird jedes Zeichen vom Ausgangsfeld ins Zielfeld kopiert.

Damit das korrekt funktionieren kann muss dst natürlich auf ein Feld zeigen, das Platz für mindestens so viele Zeichen bietet, wie das Feld von src enthält (bis zu der abschließenden 0 einschließlich, bei "Hallo" also 6).

Du erstellst allerdings einfach einen const wchar_t* mit dem Wert 0. Das "const" darin verhindert sowieso Schreibezugriffe, weshalb dein Code nicht kompiliert werden kann. Wenn du durch den cast zu (wchar_t*) das const entfernst, dann brich er im Debugmodus mit einer Ausnahme (Zugriffsverletzung beim Lesen an Position 0x00000000.) ab. (denn String2 ist 0, also hexadezimal 0x00000000)
Deshalb sind C-Style casts imo böse. static_cast, reinterpret_cast und co. sind die bessere Wahl, denn reinterpret_cast würde sich hier direkt darüber beschweren (in Form eines Compilerfehlers), dass Qualifizierer verloren gehen (das const).

Korrekt müsste dein Code ungefähr so aussehen:

C-/C++-Quelltext

1
2
3
4
LPCWSTR String1 = L"Hallo";
// Array mit mindestens 6 Elementen. Mehr schadet nicht, weniger schon.
wchar_t String2[6] = {0}; // Initialisierung setzt alle Werte des Feldes auf 0. Nicht unbedingt notwendig, aber sicherer.
wcscpy(String2, String1);


Auch wenn C-Strings ein sehr gutes Training für den Umgang mit Zeigern und Feldern sind, für den produktiven Einsatz ist std::string (bzw. std::wstring) viel besser geeignet. Dann würde sich dein Code auf folgenden, deutlich weniger fehleranfälligen und deutlich eleganteren Code reduzieren:

C-/C++-Quelltext

1
2
std::wstring String1 = L"Hallo";
std::wstring String2 = String1;
Signaturen werden überbewertet

4

14.11.2010, 20:12

Hi GR-PA,
Danke für die ausführliche Hilfe.
Das mit dem const hatte ich wohl gar nicht verstanden, das erklärt, dass mir der Compiler den Parameter nicht abnehmen wollte. Ich habe jetzt aus meinem Array mit wchar_t Pointer ein Array mit wchar_t-Arrays gemacht.

Ich hab jetzt meine Verwaltung für Texturen fertig bekommen(hätte nie gedacht, dass ich so was mal sagen könnte).

Ich hab noch ne Frage, kann ich einen wchar_t* auch als Parameter in printf() verwenden?
Also,

C-/C++-Quelltext

1
2
3
LPCWSTR String1 = L"Hallo";

printf("Das ist meine Zeichenkette:%s", String1);


Danke nochmal,
Diddus

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

5

14.11.2010, 20:20

jap das geht natürlich, nur nicht mit printf sodern wprintf. viele funktionen in c++ haben ein w-präfix, wenn du mit wide-chars arbeitest: wstring, wprintf, wcout, ...^^

6

14.11.2010, 20:25

Danke,
hätt ich eigentlich auch selbst drauf kommen können ?( .

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

7

14.11.2010, 21:37

Die lange, erklärende und hilfreichere Version von TGGCs Post (und die korrektere denn er initialisiert schließlich seine Variablen...)
a) Kennst du denn den Post, auf den ich geantwortete habe?
b) und selbst dann, wenn man p initialisiert, muss *p nicht initialisiert sein

Werbeanzeige