このブログを検索

2013-07-24

TCHAR型

完全にメモ

http://paken.s1.hayasoft.com/sb/log/eid13.html

TCHAR型のススメ
2007年01月31日 水曜日 | Paken > Iketaki |
C/C++でWindowsプログラミングをやり始めたとき、誰もが一度は嫌になるあの謎のデータ型。
"LPCTSTR"なんてのはその典型例です。
しかし、これが何かを知らぬまま放っておいてる、ということが意外とありがちなんですよね。
というわけで、一応簡単に解説しておくことにしよう、と思ったまでです。
※ C/C++を使った一般的なWindowsプログラミングをする方向けです。
※ 開発環境は、Microsoft Visual C++ 2005 を想定しています。

1.UNICODE
文字コードとはつまり、数値と文字の関係を示したものです。
文字'a'は128で表し、文字'b'は129で表し・・・と文字と数値が一対一で対応して定められています。(数値は適当です)
UNICODEも、その文字コードの一種で、古い文字コードのASCIIに比べて新しいものです。
NT系のWindowsには全て対応しているので、現在のほとんどの環境がUNICODE対応となっています。
だったら、プログラムもUNICODEに対応させた方が良いですね。

2.TCHAR型
C#という新しい言語のchar型はUNICODEですが、C/C++言語では、char型はASCII、古い文字コードです。
C/C++言語でUnicodeの文字を表すにはwchar_t型を使い、VC++ならWCHAR型とtypedefされています。
というわけで、UNICODE対応プログラムを作るにはWCHAR型を使えばOKです。

・・・OKなのですが、実はもっと良い型があります。
TCHAR型です。
こいつは何かというと、ASCIIとUNICODE両方に切り替えることが出来る万能型です。
コンパイラの設定で、UNICODEを使用する設定にすれば、UNICODEを使用し、そうでなければWindows9x系でも動作するASCIIを使用することになります。
非常に簡単に両方に対応しているプログラムが生成できるので、プログラムを作成する際にはTCHAR型をお勧めします。

3.文字または文字列の表し方
TCHAR chara;
chara = 'a';

上のコードは間違いです。なぜでしょうか。
char型で在れば問題ないのですが、ここではTCHAR型を宣言しているため、'a'がchar型だと認識されてしまうのです。
そのため、TCHAR型の文字を表すには、_TマクロまたはTEXTマクロを使用します。

TCHAR chara;
chara = _T('a');
// あるいは
chara = TEXT('a');

文字列の場合でも同じく、_T("PAKEN")、TEXT("PAKEN")、と記述してください。
(ちなみに、WCHAR型の場合は頭にLをつけ、L'a'、L"PAKEN"、などと表します)

4.謎のデータ型LPCTSTR
さて、char、WCHAR、TCHARの違いがわかったところで、一気に文字列を表すデータ型を見てみましょう。

LPSTR = char*
LPCSTR = const char*
LPWSTR = WCHAR*
LPCWSTR = const WCHAR*
LPTSTR = TCHAR*
LPCTSTR = const TCHAR*

お分かりですね。
LPCTSTRはTCHAR型の文字列なわけです。
今までchar型の文字列をLPCTSTRに強引にキャストして使っていた人もいたのではないでしょうか?
コンパイラの設定でUNICODEを使用しないようにすれば、TCHAR型はchar型に変換されるので、使うことが出来ます。
しかし、UNICODEを使用する設定にしていた人は、TCHAR型がWCHAR型に変換されるため、エラーが発生するはずです。

このような間違いを防ぐためにも、最初からchar型ではなくTCHAR型を使うことが推奨されているのです。

5.注意点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd);

見慣れたWinMain関数ですね。ですが、ここには問題点が一つあります。
お分かりですね。第3引数にchar型の文字列であるLPSTRが使われています。
ちゃんとTCHAR型のLPTSTRにしてあげなくてはなりません。
そのためには、WinMainの頭に_tをつけてあげます。なお、tchar.hをインクルードします

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nShowCmd);

これで問題ないですね。

ほとんど全てのWin32APIは、LPCTSTRまたはLPTSTRを使用しているので、私たちは気にする必要がありません。
ですが、このままだとstrcpyやfopenなど、C言語標準ライブラリ関数が使えなくなります。
でもご安心を。ちゃんとtchar.hにTCHAR型用に定義されています。

(tchar.hに定義されている例)
strcpy() → _tcscpy()
fopen() → _tfopen()
atoi() → _ttoi()
sprintf() → _stprintf()

何を使用すればよいのかわからなくなったら、tchar.h内を検索してみましょう。
TCHAR型を使用した代わりの関数が見つかります。

6.おわりに
実際やることは大したことないですがやたらと長くなってしまいました・・・
ほとんどの人は知っていることだとは思いますが、これは非常に重要なことです。
この記事を読んで初めて知った人は、出来るだけTCHAR型を使用して書くようにしましょう。

今の時代、C/C++を使用してWindowsプログラミングをする人すらあまりいませんからね。
デフォルトUNICODE対応のC#でなんら問題はないのです。

2013-07-03

centosのVMファイルを移動した後にネットワークに繋がらない時

/etc/init.d/network restartをした後、次のようなメッセージが出る。
Device eth0 does not seem to be present, delaying initialization
VMファイルを移動した後にMACアドレスの古い情報が残っているのが原因

解消方法
ifconfig -a でMACアドレス調べる
/etc/sysconfig/network-scripts/ifcfg-eth0 のHWADDRを変更
/etc/udev/rules.d/70-persistent-net.rules のeth1を消してeth0のMACを変更
reboot
http://dharry.hatenablog.com/entry/20120307/1331055287