Visual Studio 2019 C++: _DEBUG _WINDOWS _WIN32 _WIN64 _UNICODE NDEBUG WIN32 WIN64 UNICODE のメモ
シンボル | 自動的に定義される?(predefined macro?) | VSが新規作成で構成に追加? | そもそも何? | 効果ある?(*2) |
---|---|---|---|---|
_DEBUG |
yes ( msbuild ) |
yes ( Debug ) | デバッグビルドを意味する識別用にmsbuild がプロジェクトの Configuration -> Advanced -> Use Debug Libraries が Yes で /LDd /MDd /MTd が有効になる場合に自動的に定義される。但し、プロジェクト作成時にConfiguration(Debug) -> C/C++ -> Preprocessor -> Preprocessor にも明示的に追記される。 |
yes |
_WINDOWS |
no (*3) | yes | Windows向けを意味する識別用の定義。プロジェクト作成時にConfiguration -> C/C++ -> Preprocessor -> Preprocessor に明示的に追記される。(*3) | no |
_WIN32 |
yes ( cl ) |
no | Windows の 32-Bit 版または 64-Bit 版で動く事を意味する識別用に cl によって自動的に定義される。 |
yes |
_WIN64 |
yes ( cl ) |
no | Windows の 64-Bit 版で動く事を意味する識別用に cl によって自動的に定義される。 |
yes |
_UNICODE |
yes ( msbuild + ps ) (*1) |
yes | UNICODEの使用を意味する識別用にプロジェクト作成時に自動的にプロパティーシートとして設定が追加され、 Configuration -> C/C++ -> Preprocessor -> Preprocessor に追記される %(PreprocessorDefinitions) を介する形で追加される。実行効果的としては Win32 API や _T マクロが W になったりする。 |
yes |
NDEBUG |
no | yes ( Release ) | デバッグビルドではない=リリースビルドを意味する識別用の定義。プロジェクト作成時に Configuration -> C/C++ -> Preprocessor -> Preprocessor に明示的に追記される。 | yes |
WIN32 |
no | yes ( x86 ) | Windows の 32-Bit 版向けを意味する識別用の定義。プロジェクト作成時に Configuration -> C/C++ -> Preprocessor -> Preprocessor に明示的に追記される。 (*4) | nope, ... yup... (*4) |
WIN64 |
no | no | WIN32に対応したWIN64の定義について何か仕様があるような気がしてユーザーが定義する事のある何か。 | no |
UNICODE |
yes ( msbuild + ps ) (*1) | yes | UNICODEの使用を意味する識別用に定義される。プロジェクト作成時に _UNICODE と一緒に同様に追加される。 |
no |
(*1): プロジェクト作成後に構成のプリプロセッサーの定義から $(PreprocessorDefinitions)
を削除または;
区切りを忘れて無効となる書き換えを行ったりすると Character Set に Use Unicode Character Set を設定していても定義されなくなってしまうので少しそのあたりの取り扱いには注意が必要です。
(*2): この列における「効果」は Windows SDK で分岐に使われていたりする効果です。例えば WIN64
は Visual Studio が直接扱ったり Windows SDK にそれを使うコードが含まれたりはしていませんが、しばしばユーザーが独自に定義して使用している事はあります(たいてい_WIN64
を使った方がよいとは言え実際にWIN64
が使われているコードもしばしば遭遇します)。
(*3): 一見、 _WIN32
や _DEBUG
のように predefined macro のような気配を持っていますが、違います。Visual Studio はプロジェクト作成時に _WINDOWS
を構成へ自動的に追記(VS .net 以降 VS 2019 現在まで)しますが、実際のところ意味はありません(対象プラットフォームが Windows かソースコードで #if
する用途では _WIN32
が一般的に使われていますし、 predefined macro なのでそちらの方が安心です)。 Windows SDK では内部的に _WINDOWS_
というよく似た定義は使っていますが _WINDOWS
は使っていません。
(4): VS2019 の時代では(おそらく)完全に MSDN などの Microsoft 公式の情報がオンライン上に現存しないアンドキュメント化&実行効果的にもおまじない化したゆるふわ CPP 定義のようにも思え…ますが、実は現行の Windows SDK の一部でも実際に使われているので、 Win32 API の一部は WIN32
を明示的に追加定義してビルドしないと期待動作しない可能性があります。具体的に言うと WinSock2.h
を使いたい場合とか。WIN32
が未定義の場合、 Windows SDK の一部のヘッダーでは 16-Bit 時代の Windows 向けにコードが分岐したりします。ごく一部の機能を使わなければ WIN32
を定義しなくても現行の Windows SDK のほとんどの機能は問題無く使えます。しかし、執筆現在の時代では、公式な資料がオンライン上に現存
しません(たぶん)(5)。
(*5): 著者の記憶からこの定義の存在について歴史的経緯を思い出してみると、 Visual C++ 6.0 かもう少し後くらいの時代に、それまで WIN32
を使う事になっていた"お約束"をMicrosoftが「これからは_WIN32
を使おうよ」と変更した…とかあったような気がしないでもないような…どうだったかな…的な何かです。そういえばもうずいぶん昔、 cygwin か mingw の環境から winsock2 を使う必要があったときにちょっとだけ WIN32
に "おこ" した気もしますが…もうほぼ思い出せる記憶はありません…。
WIN32
に関する明確な仕様や歴史的経緯のわかる資料についての情報提供の呼びかけ
私のTL見てくれそうな歴戦のC++er各位で WIN32 がMSVC++で扱われるようになった初期の経緯や背景を覚えている人、いる? _WIN32 じゃなくてね。たぶん MSVC++6.0の頃のCD-ROM入りだったMSDNとかには WIN32 について公式に言及されていたのだと思うけれど…。もちろん、より古い話もあれば歓迎です。
— デス味(デス・ウェイ)のうさぎ=ネオウサギデス // Usagi Ito (@USAGI_WRP) 2019年12月5日
私が C++ を"当時のドシロウトなり"でもそれなりに使うようになったのは実質的には Microsoft Visual C++ 6.0 からです。それ以前は Microsoft Visual Basic 4.0 から 6.0 時代までの旧式(.netではない)の Visual Basic で Windows の GUI アプリを作っていました。処理速度の限界に耐えられなくなり、 C++ デビューした昔ばなし…はまた機会があればメモを残す事にします。
当時は C++ の言語仕様と VC++ 6.0 の言語標準からのずれがどうこうとごちゃごちゃ言えるほどの知識も無く、CD-ROMで配布されていた MSDN (当時のMSDNは翻訳クオリティーがまともだったので日本語でも読みやすかったし、謎のリンク切れも無く快適だったのです…)が教科書みたいなものでした。
そのような次第なので、私の当時やそれ以前の C++ や VC++ に関する知識は存在しないか、後付けで勉強したか、または想像が記憶を捏造してしまっている可能性も十分にあります。それで、今回気になったために ↑ のような情報提供の呼びかけをふんわりしてみたのでした。
追記: このメモはなんなの?
VS2019でC++プロジェクトを扱う際に、MSVC++での開発で頻出するCPPマクロ定義について、"じっさい"のところ構成などで明示的に定義する必要がある/ないを判断する参考用です。構成が多数あり複雑になりがちな場合に少しでも保守コストを軽減したい、そんなときに何が要らないか気になったので整理しました。