今回は、C++でよく出てくる「文字列リテラルの L とは何か」、そして「/ と の違い」について解説していきます。
「L"..." の L って何のために付けるの?」
「パスの区切りが だったり / だったり、何が違うの?」
「 ってなんで2つ書くの?」
こんな疑問はありませんか?
特にDirectXやWindows APIを触り始めると、L"assetsplayer.png" のような書き方が急に出てきて戸惑いますよね。どちらもC++の文字列リテラルの基礎で、意味が分かればスッキリします。面接で問われることもあるポイントです。
この記事を読み終えると、あなたはLプレフィックスの意味・ワイド文字が必要な理由・バックスラッシュを2つ書く理由・初心者がハマりやすいミスをしっかり理解できると思いますので、ぜひ最後まで読んでいただけると嬉しいです。文字列の基礎はstringとchar配列の違いの記事もあわせてどうぞ。
Lプレフィックスとは?
L"..." の L は、ワイド文字列リテラルを表す目印です。ざっくり言うと「1文字を2バイト以上で扱う文字列」です。
"hello" // const char* 1文字 = 1バイト(ASCII / UTF-8)
L"hello" // const wchar_t* 1文字 = 2バイト(Windowsでは UTF-16)普通の "hello" は char の配列ですが、L を付けると wchar_t(ワイド文字)の配列になります。この型の違いが、あとで効いてきます。
なぜワイド文字(L)が必要なのか
理由は、Windows APIが内部でUTF-16(wchar_t)を使っているからです。たとえば画像を読み込むDirectXTexの関数は、こういうシグネチャになっています。
HRESULT LoadFromWICFile(
const wchar_t* szFile, // ← wchar_t* を要求している
...
);この関数に "player.png"(char*)を渡すと型が合わずコンパイルエラーになります。L"player.png" と書いて wchar_t* にする必要があるわけです。「Windows APIが要求しているから付ける」のが一番の理由です。
日本語パスを安全に扱える
もう一つ大事なのが日本語ファイル名です。char*(ANSI)だと、日本語を含むパスで文字化けや読み込み失敗が起きがちです。
// wchar_t なら日本語パスも安全に扱える
L"assetsテクスチャプレイヤー.png"Windowsで日本語ファイル名を扱うなら、ワイド文字が事実上必須です。これが根本の理由になります。
その他のプレフィックス(参考)
L 以外にも、文字コードを指定するプレフィックスがあります。今すぐ覚えなくても大丈夫ですが、こういう仲間がいると知っておくと安心です。
"hello" // char 実装依存(ASCII / UTF-8 など)
L"hello" // wchar_t Windowsでは UTF-16
u8"hello" // char8_t UTF-8(C++20)
u"hello" // char16_t UTF-16
U"hello" // char32_t UTF-32/ と の違い
次は、ファイルパスの区切り文字の話です。まず結論から。
"assetstexturesplayer.png" // Windows流(バックスラッシュ)
"assets/textures/player.png" // Unix流(スラッシュ)もともとWindowsはバックスラッシュ、Linux/macOSはスラッシュでパスを区切る、という文化の違いです。
なぜ と2つ書くのか
ここが最大のポイントです。(バックスラッシュ)は、C++の文字列の中ではエスケープシーケンスの開始記号として予約されています。
"n" // 改行
"t" // タブ
" " // ヌル文字
"" // バックスラッシュそのもの
""" // ダブルクォートつまり、バックスラッシュ1文字を表したいときは と2つ書く必要があります。もし1つで書くと、次の文字とくっついて別の意味になってしまいます。
"assetstexturesplayer.png"
// ~~ ここが t と解釈され、タブ文字になってしまう!t がタブ、p は…と、意図しない解釈でパスが壊れます。だから と書くわけです。
Windowsではどちらでも動く
実は、Windows APIは両方を受け付けます。内部で自動的に変換してくれるためです。
L"assetstexturesplayer.png" // OK
L"assets/textures/player.png" // OK(こちらも動く)どっちを使うべき?
個人的には /(スラッシュ)をおすすめします。理由は3つです。
- エスケープが不要で読みやすい(
のごちゃつきがない) - クロスプラットフォーム対応(Linux/macOSでもそのまま動く)
- タイプミスが減る(
の書き忘れバグがなくなる)
ただし、既存コードが で統一されているなら、混在させず統一するほうが優先です。読みやすさは一貫性から生まれます。
【重要】私が実際に文字列リテラルで困った体験談
DirectXでテクスチャを読み込む処理を書いていたとき、パスをコピペで "assetstexturesplayer.png" とバックスラッシュ1つで書いてしまい、「ファイルが見つからない」と言われ続けて小一時間ハマりました。
原因は t がタブ文字になっていたこと。パスの文字列自体が壊れていたので、当然ファイルは見つかりません。 に直したら一発で読めました。それ以来、パスは / で書くようにしています。
もう一つ。LoadFromWICFile に L を付け忘れて "player.png" を渡し、「const char* から const wchar_t* に変換できない」というエラーで固まったこともあります。エラー文の wchar_t を見て「あ、L か」と気づけるようになると、この手のエラーは怖くなくなります。
文字列リテラルのよくある失敗例と対処法
①パスをバックスラッシュ1つで書く
体験談のとおり、t などに化けてパスが壊れます。\ と2つ書くか、いっそ / で書くのが安全です。
②Lの付け忘れ・付けすぎ
wchar_t* を要求する関数には L が必要。逆に char* の関数に L"..." を渡してもエラーです。関数が要求している型に合わせるのが基本です。エラー文の char / wchar_t を見て判断しましょう。
③char文字列とwchar_t文字列を混ぜる
std::string(char系)と std::wstring(wchar_t系)はそのままでは連結・代入できません。プロジェクト内でどちらを使うか統一しておくと、変換地獄を避けられます。
注意点
Lは関数がwchar_t*を要求するときに付ける- パスの
は\と2つ。迷うなら/が安全 - char系とwchar_t系はプロジェクトでどちらか統一する
まとめ
L"..."はワイド文字列。Windows APIがwchar_t*を要求するから付ける- 日本語パスを安全に扱うにもワイド文字が有効
はエスケープ記号なので、1文字表すには\と書く- Windowsは
/でも動く。読みやすさ重視なら/、ただし統一が最優先
L とバックスラッシュは、DirectXやWindows APIを触り始めた人が最初につまずく定番ポイントです。意味さえ分かれば怖くないので、まずは「パスは / で書く」から始めてみてください。


