2010-11-09 9 views
5

Ho un'applicazione UNICODE in cui viene utilizzato _T (x) definito come segue._T() modifiche macro per i dati dei caratteri UNICODE

#if defined(_UNICODE) 
#define _T(x) L ##x 
#else 
#define _T(x) x 
#endif 

Capisco che L venga definito su wchar_t, che sarà 4 byte su qualsiasi piattaforma. Perfavore, correggimi se sbaglio. Il mio requisito è che ho bisogno che L sia 2 byte. Così come hack del compilatore ho iniziato a usare flag -fshort-wchar gcc. Ma ora ho bisogno che la mia applicazione venga spostata su zSeries dove non vedo l'effetto del flag -fshort-wchar in quella piattaforma.

Per poter trasferire la mia applicazione su zSeries, ho bisogno di modificare la macro _T() in modo tale che anche dopo aver usato L ## x e senza usare flag -fshort-wchar, ho bisogno di ottieni 2 byte di dati di carattere ampio. Qualcuno può dirmi come posso cambiare la definizione di L in modo da poter definire L come 2 byte sempre nella mia applicazione.

+3

per quanto ne so, wchar_t è 2bytes larga su Windows, quindi la dimensione di wchar_t è l'implementazione dipendente. – nothrow

+1

'wchar_t' è normalmente usato come tipo di base per' WCHAR', che è certamente largo 2 byte. Funzioni come 'MessageBoxW' hanno argomenti' WCHAR * ', quindi avere' WCHAR' e 'wchar_t' identici rende la programmazione di Windows molto più semplice. – MSalters

+0

L è solo il carattere 'L'. Non viene definito come qualcosa. In C++, L "Hello World" definisce semplicemente una stringa * letterale * *. Ma la L non viene sostituita da nulla. – jalf

risposta

5

Non è possibile - non senza supporto C++ 0x. C++ 0x definisce i seguenti modi per dichiarare stringhe:

  • "stringa di caratteri char in qualche implementazione definita codifica" - char
  • u8 "stringa di caratteri utf8" - char
  • u "stringa di caratteri UTF16" - char16_t
  • U "stringa di caratteri UTF-32" - char32_t
  • L "stringa di wchar_t in qualche codifica attuazione definito" - wchar_t

Fino C++ 0x è ampiamente supportato, l'unico modo per codificare una stringa UTF-16 in modo multi-piattaforma è quello di suddividerlo in pezzi:

// make a char16_t type to stand in until msvc/gcc/etc supports 
// c++0x utf string literals 
#ifndef CHAR16_T_DEFINED 
#define CHAR16_T_DEFINED 
typedef unsigned short char16_t; 
#endif 

const char16_t strABC[] = { 'a', 'b', 'c', '\0' }; 
// the same declaration would work for a type that changes from 8 to 16 bits: 

#ifdef _UNICODE 
typedef char16_t TCHAR; 
#else 
typedef char TCHAR; 
#endif 
const TCHAR strABC2[] = { 'a', 'b', 'b', '\0' }; 

La macro _T in grado di fornire solo la merce su piattaforme dove wchar_t sono 16 bit di larghezza. E, l'alternativa non è ancora veramente cross-platform: la codifica di char e wchar_t è definita dall'implementazione, quindi "a" non codifica necessariamente il punto di codice unicode per "a" (0x61). Quindi, per essere rigorosamente accurati, questo è l'unico modo di scrivere la stringa:

const TCHAR strABC[] = { '\x61', '\x62', '\x63', '\0' }; 

Che è semplicemente orribile.

+0

Attenzione, su un IBM zSeries 'a' è ancora uguale a' 0x61', ma 'j' non è' 0x6a'. – MSalters

0

Ah! Le meraviglie della portabilità :-)

Se si dispone di un compilatore C99 per tutte le piattaforme, utilizzare int_least16_t, uint_least16_t, ... da <stdint.h>. La maggior parte delle piattaforme definisce anche int16_t ma non è necessario che esista (se la piattaforma è in grado di utilizzare esattamente 16 bit alla volta, è necessario definire il typedef int16_t).

Ora avvolgere tutte le stringhe in array di uint_least16_t e assicurarsi che il codice non si aspetta valori di uint_least16_t per avvolgere a 65535 ...

+0

Non risolve il problema - non hai ancora un modo per creare letterali 'const uint_least16_t []'. – MSalters

+1

Sto usando il compilatore GCC. C'è qualche altro flag del compilatore GCC diverso da -fshort-wchar per cambiare la dimensione di wchar_t. –

+0

@MSalters: 'const uint_least16_t data [] = {'f', 'o', 'o', 'b', 'a', 'r', '\ 0'};' – pmg