【C++】文字列リテラルのLとは?|ワイド文字とパス区切りの意味を初心者向けに解説

C++

今回は、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 がタブ文字になっていたこと。パスの文字列自体が壊れていたので、当然ファイルは見つかりません。 に直したら一発で読めました。それ以来、パスは / で書くようにしています。

もう一つ。LoadFromWICFileL を付け忘れて "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を触り始めた人が最初につまずく定番ポイントです。意味さえ分かれば怖くないので、まずは「パスは / で書く」から始めてみてください。

関連記事