TCHARはまだ関連していますか?


87

私はWindowsプログラミングに不慣れで、Petzoldの本を読んだ後、次のように思います。

文字列を宣言するためにTCHAR型と_T()関数を使用することはまだ良い習慣ですか、それとも新しいコードでwchar_tL""文字列を使用する必要があるのですか?

Windows 2000以降のみを対象とし、コードは最初からi18nになります。

回答:


15

今日新しいプロジェクトを行っている場合でも、TCHAR構文を使用します。それを使用することとWCHAR構文の間にそれほど実用的な違いはなく、私は文字タイプが何であるかを明示するコードを好みます。ほとんどのAPI関数とヘルパーオブジェクトはTCHAR型(例:CString)を使用するため、それを使用するのは理にかなっています。さらに、ある時点でASCIIアプリでコードを使用することにした場合、またはWindowsがUnicode32に進化した場合など、柔軟性が得られます。

あなたがWCHARルートに行くことに決めたなら、私はそれについて明白になります。つまり、CStringの代わりにCStringWを使用し、TCHARに変換するときにマクロをキャストします(例:CW2CT)。

とにかく、それは私の意見です。


確かに、それは文字エンコーディングが最終的に「再び」変更されたときにも機能するものです。
Medinoc 2014

11
文字タイプが何であるかを明示するコードを好むので、時々これと時々それであるタイプを使用しますか?非常に説得力があります。
deduplicator 2015年

4
-1は、@ Deduplicatorによって指摘された不整合、および何でもかまいません(通常、複数の特定の値についてテストされない)マクロを使用するための負のペイオフアドバイスの場合です。
乾杯とhth。-アルフ2016

90

簡単な答え: いいえ

すでに書いた他のすべてのように、多くのプログラマーはまだTCHARと対応する関数を使用しています。私の謙虚な意見では、全体の概念は悪い考えでした。UTF-16文字列処理は、単純なASCII / MBCS文字列処理とは大きく異なります。両方で同じアルゴリズム/関数を使用する場合(これはTCHARのアイデアの基になっています!)、単純な文字列の連結よりも少し多くのことを行うと、UTF-16バージョンで非常に悪いパフォーマンスが得られます(解析など)。主な理由は代理人です。

唯一の例外を除いて、あなたがたときに本当にUnicodeの私は、新しいアプリケーションでは、過去からこの荷物を使用する理由を見ていないサポートしていないシステムのためのアプリケーションをコンパイルする必要があります。


6
おもしろい事実:UTF-16はNTプラットフォームに常に存在するとは限りませんでした。代理コードポイントは、NT4がリリースされたのと同じ1996年にUnicode2.0で導入されました。IIRC(Windows 2000を含む)まで、すべてのNTバージョンはUCS-2を使用していました。これは、事実上、各文字が1つのコードポイントで表現可能である(つまりサロゲートがない)と想定したUTF-16のサブセットです。
0xC0000022L 2012

3
ところで、私はそれTCHARがもう使われるべきではないことに同意しますが、これが悪い考えであったことに同意しません。また、私はと思いならばあなたが選ぶ代わりに使用しての明示的であることをTCHAR明示的でなければならどこでも。つまり、宣言でTCHAR/ _TCHAR(など_tmain)を含む関数も使用しません。簡単に言えば、一貫性を保つ。+1、それでも。
0xC0000022L

3
それ導入されたときは良い考えでしたが、新しいコードでは無関係であるはずです。
エイドリアンマッカーシー

4
あなたTCHARは、最初に導入された目的を誤って伝えています。Win9xおよびWindowsNTベースのバージョンのWindows用のコードの開発を容易にするため。当時、Windows NTのUTF-16実装はUCS-2であり、文字列の解析/操作のアルゴリズムは同じでした。代理人はいませんでした。また、サロゲートを使用しても、DBCS(Windowsでサポートされている唯一のMBCSエンコーディング)とUTF-16のアルゴリズムは同じです。どちらのエンコーディングでも、コードポイントは1つまたは2つのコードユニットで構成されます。
iInspectable 2015年

FormatMessage()を使用して、値をWSAGetLastError()から印刷可能なものに変換するとします。WSAGetLastError()のドキュメントには、LPTSTRをバッファーへのポインターとして使用すると記載されています。私は本当に多くの選択肢がありませんが、TCHARを使用する以外にありませんか?
エドワードフォーク2016

80

Saschaに同意する必要があります。基礎となる前提TCHAR/ _T()/などは、あなたが「ANSI」ベースのアプリケーションを作成して、魔法のようにマクロを定義することによって、それをUnicodeサポートを与えることができるということです。しかし、これはいくつかの悪い仮定に基づいています。

ソフトウェアのMBCSバージョンとUnicodeバージョンの両方を積極的に構築していること

そうでなければ、あなた滑ってchar*、多くの場所で普通の弦を使うでしょ

_T( "...")リテラルで非ASCIIバックスラッシュエスケープを使用しないこと

「ANSI」エンコーディングがたまたまISO-8859-1でない限り、結果のリテラルchar*wchar_t*リテラルは同じ文字を表しません。

そのUTF-16文字列は「ANSI」文字列と同じように使用されます

彼らはそうではありません。Unicodeは、ほとんどのレガシー文字エンコーディングには存在しないいくつかの概念を導入しています。サロゲート。文字を組み合わせる。正規化。条件付きで言語に依存するケーシングルール。

そしておそらく最も重要なのは、UTF-16がディスクに保存されたりインターネット経由で送信されたりすることはめったにないという事実です。UTF-8は外部表現に好まれる傾向があります。

アプリケーションがインターネットを使用していないこと

(今、これはあなたのソフトウェアにとって有効な仮定かもしれませんが...)

Webは、UTF-8多数のまれなエンコーディングで実行されます。このTCHAR概念は、「ANSI」(UTF-8にすることはできません)と「Unicode」(UTF-16)の2つのみを認識します。Windows API呼び出しをUnicode対応にするのに役立つかもしれませんが、Webアプリや電子メールアプリをUnicode対応にするのには役に立たないのです。

Microsoft以外のライブラリを使用しないこと

他の誰も使用しませんTCHARPocostd::stringUTF-8を使用しています。 SQLiteにはそのAPIのUTF-8およびUTF-16バージョンがありますが、ありませんTCHARTCHAR標準ライブラリにも含まれていstd::tcoutないので、自分で定義する場合を除いて、ありません。

TCHARの代わりに私がお勧めするもの

有効なUTF-8ではないファイルを読み取る必要がある場合を除いて、「ANSI」エンコーディングが存在することを忘れてください。忘れてくださいTCHAR。常に「W」バージョンのWindowsAPI関数を呼び出します。 #define _UNICODE誤って「A」関数を呼び出さないようにするためです。

文字列には常にUTFエンコーディングを使用してください。文字列にはUTF-8、char文字列にはUTF-16(Windowsの場合)またはUTF-32(Unixライクなシステムの場合)wchar_ttypedef UTF16そして、UTF32文字の種類は、プラットフォームの違いを避けるために。


6
2012年の呼びかけ:今でも維持されるべきアプリケーションがまだあります#define _UNICODE。送信の終了:)
0xC0000022L 2012

12
@ 0xC0000022L質問は新しいコードについてでした。古いコードを維持するときは、明らかにコードが記述されている環境作業する必要があります。COBOLアプリケーションを保守している場合、COBOLが優れた言語であるかどうかは関係ありません、あなたはそれに固執しています。また、TCHARに依存するアプリケーションを保守している場合、それが適切な決定であったかどうかは関係ありません。
jalf 2012年

2
確かに、TCHARはCOBOLでない限り役に立ちません)
Pavel Radzivilovsky 2012年

1
_UNICODEジェネリックテキストマッピングがCRTでどのように解決されるかを制御します。Windows APIのANSIバージョンを呼び出したくない場合は、を定義する必要がありますUNICODE
iInspectable 2016

18

それがまだ実際に行われているかどうか疑問に思っているなら、そうです-それはまだかなり使用されています。TCHARと_T( "")を使用している場合、誰もあなたのコードを面白く見ることはありません。私が現在取り組んでいるプロジェクトは、ANSIからUnicodeに変換することです。そして、ポータブル(TCHAR)ルートを使用します。

しかしながら...

私の投票は、すべてのANSI / UNICODEポータブルマクロ(TCHAR、_T( "")、およびすべての_tXXXXXX呼び出しなど)を忘れて、どこでもユニコードを想定することです。ANSIバージョンが必要になることがないのであれば、ポータブルであるという意味は本当にわかりません。私はすべてのワイド文字関数とタイプを直接使用します。すべての文字列リテラルの前にLを付けます。


3
ANSIバージョンが必要な別の場所で使用したいコードを記述したり、(ニックが言ったように)WindowsがDCHARなどに移行したりする可能性があるため、代わりにTCHARを使用することをお勧めします。 WCHAR。
arke 2010年

WindowsがUTF-32に切り替わるとは思えません。
dan04 2012年

7
-UTF-16推奨の場合は-1。これにより、移植性のない(Windows中心の)コードが作成されるだけでなく、ライブラリでは受け入れられません。UIコードのような最も単純なケースで使用される場合でも、Windows自体でも効率的ではありません。utf8everywhere.org
Pavel Radzivilovsky 2012年

11

はじめにWindowsにプログラミングの記事MSDNのは言います

新しいアプリケーションは、常に(APIの)Unicodeバージョンを呼び出す必要があります。

TEXTTCHARのすべてのアプリケーションがUnicodeを使用する必要があるので、マクロは、今日あまり有用です。

私はに固執するだろうwchar_tL""


4
スティーブン、あなたは「Unicode」という言葉の意味を理解していない誰かによって書かれたテキストを引用しています。これは、UCS-2の混乱の時からのそれらの不幸な文書の1つです。
Pavel Radzivilovsky 2012年

2
@PavelRadzivilovsky:このドキュメントは、UnicodeUTF-16LEが一般的に交換可能に使用されるシステム用に作成されました。技術的には不正確ですが、それでも明確です。これは、同じテキストの紹介でも明示的に指摘されています。「WindowsはUTF-16エンコーディングを使用してUnicode文字を表します[...]」
iInspectable 2016

11

別のアプローチを提案したいと思います(どちらでもない)。

要約すると、UTF-8エンコーディングを想定してchar *とstd :: stringを使用し、API関数をラップする場合にのみUTF-16への変換を行います。

Windowsプログラムでのこのアプローチの詳細と正当化については、http://www.utf8everywhere.orgを参照してください


@PavelRadzivilovskyは、VC ++アプリケーションで提案を実装するときに、VC ++文字を「なし」または「マルチバイト(MBCS)」に設定しますか?私が尋ねている理由は、Boost :: Localeをインストールしたばかりで、デフォルトの文字セットはMBCSだったからです。FWIW、純粋なASCIIアプリケーションは「なし」に設定されていて、「MBCS」に設定されています(Boost :: Localeを使用するため)。これで問題なく動作します。お知らせ下さい。
キャロラインベルトラン2014

utf8everywhereが推奨するように、「Unicode文字セットを使用する」に設定します。これは追加の安全性を宣伝しますが、必須ではありません。Boost :: localeの作者はとても頭のいい人ですが、彼は正しいことをしたと確信しています。
Pavel Radzivilovsky 2014

1
UTF-8はどこマントラは、それがより頻繁に繰り返されているという理由だけで、適切なソリューションになることはありません。UTF-8は間違いなくシリアル化(ファイルやネットワークソケットなど)にとって魅力的なエンコーディングですが、Windowsでは、ネイティブUTF-16エンコーディングを使用して文字データを内部に格納し、アプリケーションの境界で変換する方が適切な場合がよくあります。1つの理由は、UTF-16が唯一のエンコーディングであり、サポートされている他のエンコーディングにすぐに変換できることです。これはUTF-8には当てはまりません。
iInspectable 2016

「..UTF-16は唯一のエンコーディングであり、サポートされている他のエンコーディングにすぐに変換できます。」どういう意味ですか?UTF-8エンコーディングを他のものに変換する際の問題は何ですか?
Pavel Radzivilovsky 2016

1
理解できません。他の何かに-何のように?例:UCS-4?何故なの?非常に簡単なようです、すべて数値アルゴリズム..
Pavel Radzivilovsky 2016

7

TCHAR/WCHAR一部のレガシープロジェクトには十分かもしれません。しかし、新しいアプリケーションの場合、私はNOと言います。

これらすべてTCHAR/WCHARものは歴史的な理由のためにそこにあります。TCHARANSIテキストエンコーディング(MBCS)とUnicodeテキストエンコーディング(UTF-16)を切り替えるための、一見すっきりした方法(偽装)を提供します。これまで、人々は世界のすべての言語の文字数を理解していませんでした。彼らは、2バイトですべての文字を表すのに十分であり、したがって、を使用した固定長の文字エンコード方式であると想定しましたWCHAR。ただし、1996年にUnicode 2.0がリリースされた後は、これは当てはまりません。

つまり、CHAR/ WCHAR/TCHARでどちらを使用する場合でも、プログラムのテキスト処理部分は、国際化のために可変長文字を処理できる必要があります。

実際にはより多くのいずれかを選択よりも実行する必要がありますので、CHAR/ WCHAR/ TCHARWindowsでプログラミングします:

  1. アプリケーションが小さく、テキスト処理を伴わない場合(つまり、テキスト文字列を引数として渡すだけの場合)は、WCHAR。を使用します。この方法はUnicodeをサポートするWinAPIを使用する方が簡単なので。
  2. それ以外の場合は、UTF-8を内部エンコーディングとして使用し、テキストをchar文字列またはstd :: stringに格納することをお勧めします。そして、WinAPIを呼び出すときにそれらをUTF-16に変換します。現在、UTF-8が主要なエンコーディングであり、UTF-8文字列を処理するための便利なライブラリとツールがたくさんあります。

より詳細な読書のためにこの素晴らしいウェブサイトをチェックしてください:http//utf8everywhere.org/


2
「UTF-8が主流のエンコーディングになりました」 -引用の2番目の部分(「ワールドワイドウェブ用」)を省略したため、これは間違っていました。デスクトップアプリケーションの場合、最も使用されているネイティブ文字エンコーディングは依然としてUTF-16です。Windowsはそれを使用し、Mac OS Xも使用し、.NETとJavaの文字列タイプも使用します。それはを占め、大規模なそこにコードの量。誤解しないでください。シリアル化用のUTF-8には何の問題もありません。しかし、多くの場合(特にWindowsの場合)、UTF-16を内部で使用する方が適切であることがわかります。
iInspectable 2016

4

そのとおり; 少なくとも_Tマクロについては。ただし、ワイド文字についてはよくわかりません。

その理由は、WinCEまたはその他の非標準のWindowsプラットフォームをより適切にサポートするためです。コードがNTに残ることが100%確実な場合は、通常のC文字列宣言を使用できます。ただし、ライブラリを移植する必要がある場合に備えて、数千行のコードを実行してどこにでも追加するよりも、Windows以外のプラットフォームでそのマクロを#defineする方がはるかに簡単なので、より柔軟なアプローチを採用するのが最善です。 WindowsMo​​bileに。


1
WinCEは、Win32と同じように16ビットのwchar_t文字列を使用します。WinCEとWin32で実行されるコードの大規模なベースがあり、TCHARを使用することはありません。
mhenry1384 2010年

2

私見ですが、コードにTCHARが含まれている場合は、間違ったレベルの抽象化で作業しています。

テキスト処理を扱うときは、最も便利文字列型を使用してください。これは、Unicodeをサポートするものになると思いますが、それはあなた次第です。必要に応じて、OSAPI境界で変換を行います。

ファイルパスを処理するときは、文字列を使用する代わりに、独自のカスタムタイプを作成してください。これにより、OSに依存しないパス区切り文字が可能になり、手動の文字列連結や分割よりもコード化が容易になり、さまざまなOS(ansi、ucs-2、utf-8など)への適応がはるかに簡単になります。 。


Unicodeには、少なくとも3つの現在のエンコーディング(UTF-8、UTF-16、UTF-32)と1つの非推奨のエンコーディング(UCS-2、現在のUTF-16のサブセット)があります。どちらを参照しますか?+1
0xC0000022L 2012

2

明示的なWCHAR以外のものを使用する理由は、移植性と効率だけです。

最終的な実行可能ファイルをできるだけ小さくしたい場合は、charを使用してください。

RAMの使用量を気にせず、国際化を単純な変換と同じくらい簡単にしたい場合は、WCHARを使用してください。

コードを柔軟にしたい場合は、TCHARを使用してください。

ラテン文字のみを使用する予定の場合は、ASCII / MBCS文字列を使用して、ユーザーがそれほど多くのRAMを必要としないようにすることもできます。

「最初からi18n」の人は、ソースコードのスペースを節約し、すべてのUnicode関数を使用するだけです。


-1

古い質問に追加するだけです:

番号

VS2010で新しいCLRC ++プロジェクトを開始します。マイクロソフト自身が使用L"Hello World"している」とナフ氏は語った。


13
CLRは、アンマネージコードとは大きく異なる環境です。それは議論ではありません
コーディグレイ

3
マイクロソフトでさえ間違いを犯します。
Pavel Radzivilovsky 2012年

6
-1質問がタグ付けされているCC++。回答は、それぞれの作成者がいつでも削除できます。これは、その規定を使用するのに良い時期です。
iInspectable 2013年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.