expertenaustausch > microsoft.* > microsoft.vc

Hans-J. Ude (19.05.2010, 10:47)
Hans-J. Ude schrieb:

>Ungünstig, falls er sich entscheidet doch auf MBCS zu bleiben, wovon
>ich mal abrate, muss er wieder alles mögliche ändern. _T("") ist schon
>richtig. Es sei denn man braucht WCHAR unabhängig vom Modell, aber so
>einen Fall kenne ich nicht.


Hatte ich noch vergessen zu erwähnen: _T("xyz") oder "xyz" direkt im
Quellcode ist nur in gaaaaaaanz seltenen Fällen sinnvoll. Dafür gibt
es die Ressourcen (Stringtable).

Hajü
Hans-J. Ude (19.05.2010, 11:10)
Ulrich Eckhardt schrieb:

>HAE? Der Datentyp TCHAR ist _abhaengig_ vom Zeichensatz, das ist doch der
>Punkt! Desgleichen CString und CreateFile, weil die von TCHAR abhaengen.


Nein, TCAHR kannst du _unabhängig_ vom Modell verwenden. Bei Unicode
mappt es auf wchar_t sonst auf char.

>Moment, auch das geht so nicht wirklich gut, weil Du keine non-PODs an eine
>Funktion mit variablen Argumenten geben darfst. Fuer den Fall oben, dass Du
>einen char-String in einen TCHAR-String reinformatieren willst, gibt es %hs


Falsch, das funktioniert so schon seit Jahren. 100%ig, egal ob Unicode
oder nicht, glaub es.

Hajü
Ulrich Eckhardt (19.05.2010, 13:57)
Hans-J. Ude wrote:
> Ulrich Eckhardt schrieb:
>>HAE? Der Datentyp TCHAR ist _abhaengig_ vom Zeichensatz, das ist doch der
>>Punkt! Desgleichen CString und CreateFile, weil die von TCHAR abhaengen.

> Nein, TCAHR kannst du _unabhängig_ vom Modell verwenden.


FILE* f = fopen(_T("C:\autoexec.bat"), "r");

Das klappt nur wenn der Zeichensatz so steht dass TCHAR ein char ist. Klar,
Du kannst immer TCHAR mit TCHAR verwenden, unabhaengig davon was TCHAR bzw
der Zeichensats so ist, aber zu behaupten dass TCHAR deswegen vom
Zeichensatz unabhaengig ist ist meinem Sprachverstaendnis nach einfach
nicht richtig.

>>Moment, auch das geht so nicht wirklich gut, weil Du keine non-PODs an
>>eine Funktion mit variablen Argumenten geben darfst. Fuer den Fall oben,
>>dass Du einen char-String in einen TCHAR-String reinformatieren willst,
>>gibt es %hs

> Falsch,


Nicht falsch.

> das funktioniert so schon seit Jahren. 100%ig, egal ob Unicode
> oder nicht, glaub es.


Ja, ich glaube Dir dass es bei Dir funktioniert.

Effektiv kommt da ein TCHAR-Zeiger an, und "%s" in CString::Format()
erwartet auch genau das.

Es gibt aber halt noch die alternative Variante dass man einfach sagt dass
man einen char-String hat (%hs), damit spart man sich Code und zur Laufzeit
wird auch nicht kurzfristig ein CString-Objekt erstellt (mit dem nach
wchar_t konvertierten oder nur kopierten String) nur um als Vorlage in den
naechsten CString reinformatiert zu werden.

Ansonsten, dass man keine non-PODs durch eine Ellipsis geben sollte sagt der
C++-Standard. Wenn ich mich recht erinnere schlaegt das bei CStrings auch
auf einigen win64 Systemen fehl, das wurde auch in dieser Gruppe mal
diskutiert.

Uli
Hans-J. Ude (19.05.2010, 16:17)
Ulrich Eckhardt schrieb:

>Hans-J. Ude wrote:
>> Ulrich Eckhardt schrieb:
>>>HAE? Der Datentyp TCHAR ist _abhaengig_ vom Zeichensatz, das ist doch der
>>>Punkt! Desgleichen CString und CreateFile, weil die von TCHAR abhaengen.

>> Nein, TCAHR kannst du _unabhängig_ vom Modell verwenden.

> FILE* f = fopen(_T("C:\autoexec.bat"), "r");


Die Funktion stammt auch noch aus den 70er Jahren des letzten
Jahrhunderts, als man von Unicode noch nichts wusste und gehört
schleunigst in die Mülltonne der Geschichte. fopen ist auch explizit
mit (char *) deklariert. Nimm

FILE* f = NULL;
int err = _tfopen_s(&f, _T("C:\\autoexec.bat"), _T("r"));

und schon hast du etwas, was unabhängig vom Zeichensatz funktioniert.

[..]
>wird auch nicht kurzfristig ein CString-Objekt erstellt (mit dem nach
>wchar_t konvertierten oder nur kopierten String) nur um als Vorlage in den
>naechsten CString reinformatiert zu werden.


Für die Handvoll Mikrosekunden nehme ich wartbaren, lesbaren und
portabelen Code gerne in Kauf. Mit portabel meine ich UC <-> MBCS.
Außerdem sollte das Beispiel im Wesentlichen zeigen, wie man einen
char schnell und elegant in einen wchat_t umwandeln kann.

Hajü
Ulrich Eckhardt (19.05.2010, 18:50)
Hans-J. Ude wrote:
> Ulrich Eckhardt schrieb:
> Die Funktion stammt auch noch aus den 70er Jahren des letzten
> Jahrhunderts, als man von Unicode noch nichts wusste und gehört
> schleunigst in die Mülltonne der Geschichte. fopen ist auch explizit
> mit (char *) deklariert.


Richtig, aber ich haette auch wfopen() nehmen koennen, gleiches Ergebnis.
Oder von mir aus

std::cout << _T('4') << _T('2') << std::endl;

fuer alle die die Fehler lieber zur Laufzeit haben. (c:

> Für die Handvoll Mikrosekunden nehme ich wartbaren, lesbaren und
> portabelen Code gerne in Kauf. Mit portabel meine ich UC <-> MBCS.


Dein Code ist nicht portabel, das ist doch das Problem. Noch nicht mal wenn
man sich auf MS Windows-Platformen unter MS Compilern beschraenkt. Dass der
Code auch noch unnoetige Konvertierungen und Speichermanagement macht ist
dabei nur marginal interessant.

Guck' mal im Netz nach der Warnung C6284, da steht's nochmal explizit dass
es nicht unterstuetzt wird. Ansonsten scheint mich meine Erinnerung nicht
zu truegen, unter win64 funktioniert es nicht mehr, wie ich im Netz gelesen
habe (u.a. auf Martin Richters Blog).

Uli
Hans-J. Ude (20.05.2010, 14:15)
Ulrich Eckhardt schrieb:

>Hans-J. Ude wrote:
>> Ulrich Eckhardt schrieb:
>>>Hans-J. Ude wrote:
>>>> Nein, TCAHR kannst du _unabhängig_ vom Modell verwenden.
>>> FILE* f = fopen(_T("C:\autoexec.bat"), "r");

>Richtig, aber ich haette auch wfopen() nehmen koennen, gleiches Ergebnis.


Nein, _wfopen ist inkompatibel zu Multibyte Umgebungen. Deswegen
wurden ja die _t... Makros eingeführt. Und selbst unter Unicode gibt
es warning C4996: '_wfopen' was declared deprecated
ich geb's auf...

>Dein Code ist nicht portabel, das ist doch das Problem. Noch nicht mal wenn
>man sich auf MS Windows-Platformen unter MS Compilern beschraenkt. Dass der
>Code auch noch unnoetige Konvertierungen und Speichermanagement macht ist
>dabei nur marginal interessant.


Doch, der funktioniert schnörkellos in Unicode und MBCS Umgebungen. No
errors, no warnings und es funktioniert tadellos. Außerdem ist
Konvertierung genau das, was der OP haben wollte. Für mich ist hier
EOD.

Hajü
Stefan Binder (20.05.2010, 14:32)
Hallo Hans-J!

> Es gibt überigens auch in Unicode builds eine Überladung
> CString::CString(char *), getestetes Beispiel:
> HOSTENT *phe;
> .
> .
> str.Format(strFormat, CString(phe->h_name), strIP);


Das funktioniert durch Zufall unter bei einem 32 Bit kompilat, da
CString als 1. Datenmember den tchar pointer auf den enthaltenen String hat.
Unter 64 Bit geht es aber schon nicht mehr (abgesehen davon das es
sowieso grundlegend falsch ist, und nur durch Zufall funktioniert).

Aktivier mal beim kompilieren die /analyze Funktion!

Hatte es auch lange so verwendet, nur hab ich es damals erklärt
bekommen, und ich habe es auch geglaubt :)

Wenn schon dann
str.Format(strFormat, CString(phe->h_name).GetString(), strIP);
(und falls strIP auch ein CString ist dort gleich nochmal (oder ein cast)!

mfg
Stefan
Martin Richter [MVP] (20.05.2010, 15:06)
Hallo Stefan!

> Das funktioniert durch Zufall unter bei einem 32 Bit kompilat, da
> CString als 1. Datenmember den tchar pointer auf den enthaltenen String
> hat.


Selbst im 32bit System funktioniert es nicht!

Stefan Kuhr (20.05.2010, 17:45)
Hallo Stefan,

On 5/20/2010 2:32 PM, Stefan Binder wrote:
> <snip>
> Unter 64 Bit geht es aber schon nicht mehr (abgesehen davon das es
> sowieso grundlegend falsch ist, und nur durch Zufall funktioniert).


Das hat irgendeiner hier in dieser Gruppe irgendwann mal behauptet und
ich konnte das nie glauben, war aber immer zu faul es selber mal
auszuprobieren. Jetzt habe ich es mal ausprobiert und ich kann nicht
bestaetigen, dass das unter x64 nicht geht. Nicht, dass ich es gut
faende, wenn jemand CStrings einer variadischen Funktion uebergibt, aber
die Behauptung, dass ein CString unter x64 sich dabei anders als unter
x86 verhaelt ist nach meinem Dafuerhalten nicht richtig.

Folgender Code:

DWORD dw = sizeof(CString);
CString str1 = _T("Hello");
CString str2 = _T("World");
DWORD dwResult = 42;
_tprintf(_T("Size is %lu, %s %s %lu\n"), dw, str1, str2, dwResult);

ergibt bei mir als x86 binary uebersetzt:

Size is 4, Hello World 42

und als x64 binary uebersetzt:

Size is 8, Hello World 42

Wenn jemand andere Erfahrungen gemacht hat, dann wuerde mich ein
konkretes Codebeispiel freuen, ansonsten tue ich hiermit fuer mich das
"CString als Ersatz fuer einen char* als Argument fuer printf geht unter
x64 nicht" als Legende ab.

Oder verstehe ich was an der ganzen Diskussion nicht?
Ulrich Eckhardt (20.05.2010, 18:00)
Hans-J. Ude wrote:
> Ulrich Eckhardt schrieb:
> Nein, _wfopen ist inkompatibel zu Multibyte Umgebungen. Deswegen
> wurden ja die _t... Makros eingeführt.


Also, Deine Aussage war: "Der Datentyp TCHAR ist unabhängig vom
Zeichensatz." Mein Kommentar dazu war dass das so nicht stimmt.

Als Test dienten zwei Funktionen die char bzw. wchar_t als Parameter nehmen.
Diese Funktionen aendern sich nicht mit dem Zeichensatz. Wenn TCHAR
unabhaengig vom Zeichensatz ("Character Set") waere, dann wuerde ein
TCHAR-Parameter bei diesen beiden Funktionen entweder immer funktionieren
oder nie. Tut er aber nicht, also ist TCHAR offensichtlich doch abhaengig
vom Zeichensatz. Genau genommen definierst Du ueber den Zeichenzatz die
Bedeutung von TCHAR, naemlich entweder als CHAR oder als WCHAR.

Ein TCHAR-Parameter passt selbstverstaendlich immer auf eine Funktion die
einen TCHAR-Parameter erwartet, unabhaengig vom Zeichensatz, aber das
bedeutet noch lange nicht dass TCHAR unabhaengig vom Zeichensatz ist!

> Und selbst unter Unicode gibt es warning C4996: '_wfopen'
> was declared deprecated


Und wieso ist das relevant?

Zu dem Rest aeussere ich mich nicht weiter, vielleichst glaubst Du ja Stefan
oder Martin.

Uli
Hans-J. Ude (20.05.2010, 19:17)
Ulrich Eckhardt schrieb:

>Hans-J. Ude wrote:
>Also, Deine Aussage war: "Der Datentyp TCHAR ist unabhängig vom
>Zeichensatz." Mein Kommentar dazu war dass das so nicht stimmt.


Wir meinen sowieso beide dasselbe, und wissen was ein char, wchar_t
und TCHAR ist. Nur ich sehe es aus der Seite des Programmierers und du
aus der des Compilers. Der Compiler löst TCHAR schon so auf, wie es
nötig ist, das muss ich nicht selber machen. Nur in gaaaaaanz seltenen
Ausnahmen ist das nötig, sonst eher schädlich.

>Als Test dienten zwei Funktionen die char bzw. wchar_t als Parameter nehmen.
>Diese Funktionen aendern sich nicht mit dem Zeichensatz. Wenn TCHAR
>unabhaengig vom Zeichensatz ("Character Set") waere, dann wuerde ein
>TCHAR-Parameter bei diesen beiden Funktionen entweder immer funktionieren
>oder nie. Tut er aber nicht, also ist TCHAR offensichtlich doch abhaengig
>vom Zeichensatz. Genau genommen definierst Du ueber den Zeichenzatz die
>Bedeutung von TCHAR, naemlich entweder als CHAR oder als WCHAR.


Schon klar, mein Reden.

>> Und selbst unter Unicode gibt es warning C4996: '_wfopen'
>> was declared deprecated

>Und wieso ist das relevant?


Nur daß man die Funktion nicht mehr benutzen sollte, sondern
stattdessen _tfopen_s, weil aus dem warning irgendwann in der Zukunft
mal ein error wird. Und was die 64-bit Geschichte angeht, das würde
ich gern ausprobieren wenn ich ein entsprechendes OS hätte.

Gruß,
Hajü
Jochen Kalmbach [MVP] (20.05.2010, 20:56)
Hallo Stefan!

> Wenn jemand andere Erfahrungen gemacht hat, dann wuerde mich ein
> konkretes Codebeispiel freuen, ansonsten tue ich hiermit fuer mich das
> "CString als Ersatz fuer einen char* als Argument fuer printf geht unter
> x64 nicht" als Legende ab.


Ja, so würde ich das auch sehen...
Der CString hat intern weder virtuelle Methoden noch sonstige Daten
ausser einem "Buffer" für den String...

Beim std:(w)string funktioniert es auf jeden Fall nicht...
Karsten Schulz (26.05.2010, 13:17)
Pointer werden nicht wild, nur die user die sie aus den augen lassen.

"Hans-J. Ude" <news> schrieb im Newsbeitrag
news:i3ae
[..]

Ähnliche Themen