web-dev-qa-db-ja.com

CおよびC ++の#includeディレクティブでバックスラッシュを使用できますか?

一般的に使用される2つのパス区切り文字があります。UnixのスラッシュとDOSのバックスラッシュです。 落ち着いて休む、クラシックマックコロン。 #includeディレクティブで使用する場合、それらはC++ 11、C++ 03、およびC99標準の規則の下で等しいですか?

41
Potatoswatter

C99は言う(§6.4.7/ 3):

文字「、\、 "、//、または/ *が、<と>の区切り文字の間のシーケンスで発生した場合、動作は未定義です。同様に、文字 '、\、//、または/ *がシーケンスで発生した場合"区切り文字の間では、動作は未定義です。

(脚注:したがって、エスケープシーケンスに似た文字シーケンスは、未定義の動作を引き起こします。)

C++ 03は言う(§2.8/ 2):

文字 'または\、または文字シーケンス/ *または//のいずれかがq-char-シーケンスまたはh-char-sequenceにある場合、または文字 "がh-char-sequenceにある場合、動作は未定義です。

(脚注:したがって、エスケープシーケンスに似た文字シーケンスは、未定義の動作を引き起こします。)

C++ 11は言う(§2.9/ 2):

Q-char-sequenceまたはh-char-sequence内の文字 'または\または文字シーケンス/ *または//のいずれかの外観は、実装定義のセマンティクスで条件付きでサポートされます。 h-char-sequence内の文字 ".

(脚注:したがって、エスケープシーケンスに似た一連の文字は、エラーになるか、実装に応じて、エスケープシーケンスに対応する文字として解釈されるか、まったく異なる意味を持つ可能性があります。)

したがって、コンパイラは#includeパスでバックスラッシュをサポートすることを選択する可能性がありますが、コンパイラベンダーがフォワードスラッシュをサポートしない可能性は低く、バックスラッシュはエスケープコードの形成により一部の実装をトリップする可能性があります。 (編集:どうやらMSVCは以前はバックスラッシュを必要としていた。おそらくDOS派生のプラットフォームの他のものも同様だった。うーん…何と言えばいいか。)

C++ 11 seemsルールを緩和しますが、「条件付きでサポートされる」は「未定義の動作を引き起こす」よりも意味のあるほど優れているわけではありません。この変更は、移植可能な標準を説明するよりも、特定の一般的なコンパイラの存在を反映するために行われます。

もちろん、これらの標準のいずれにも、パスのようなものがあるとは言われていません。そこにはあるパスがまったくないファイルシステムがあります!ただし、多くのライブラリはPOSIXやBoostなどのパス名を想定しているため、サブディレクトリ内のファイルを参照するためのポータブルな方法が必要です。

49
Potatoswatter

スラッシュが正しい方法です。プリコンパイラーは、各プラットフォームで正しいファイルを取得するために必要なことをすべて行います。

7
trojanfoe

ブラックスラッシュは未定義の動作であり、スラッシュを使用する場合でも注意が必要です。 C99標準は次のように述べています。

文字 '、\、 "、//、または/ *が、<と>の区切り文字の間のシーケンスで発生した場合、動作は未定義です。同様に、文字'、\、//、または/ *がシーケンスで発生した場合"区切り文字の間では、動作は未定義です。

6
Jens Gustedt

それはあなたが「許容できる」という意味に依存します。

スラッシュは受け入れられるが、バックスラッシュは受け入れられないという2つの意味があります。

C99、C++ 03、またはC1xを記述している場合、バックスラッシュは未定義ですが、スラッシュは有効であるため、この意味でバックスラッシュは受け入れられません。

しかし、これはほとんどの人にとって無関係です。バックスラッシュが条件付きでサポートされているC++ 1xを記述していて、コーディング対象のプラットフォームがそれらをサポートしている場合、それらは許容されます。また、バックスラッシュを定義するC99/C++ 03/C1xの「拡張方言」を作成している場合も同様です。そしてさらに重要なことに、この「許容できる」という概念は、ほとんどの場合、とにかくほとんど意味がありません。 C/C++標準では、スラッシュの意味(または条件付きでサポートされている場合のバックスラッシュの意味)は定義されていません。ヘッダー名は、実装定義の方法であるピリオドでソースファイルにマップされます。ファイルの階層があり、#includeディレクティブでそれらを移植可能に参照するためにバックスラッシュまたはスラッシュを使用するかどうかを尋ねている場合、答えは次のとおりです。どちらも移植性がありません。真に移植可能なコードを記述したい場合、ヘッダーファイルの階層を使用することはできません。実際、おそらく最善の策は、すべてを単一のソースファイルに記述し、標準ヘッダー以外の#includeは何も含めないことです。

しかし、現実の世界では、人々は「厳密にポータブル」ではなく「ポータブルで十分」を望むことがよくあります。 POSIX標準ではスラッシュの意味が義務付けられており、POSIXを超えて、Win32(およびWin64)、Symbianなどの組み込みプラットフォームおよびモバイルプラットフォーム用のクロスコンパイラなど、ほとんどの最新プラットフォームは、少なくともPOSIXの方法でスラッシュを扱います。 C/C++ #includeディレクティブ。ソースツリーを取得したり、メイクファイルなどを処理したりできないプラットフォームはおそらくないでしょう。そのため、#includeディレクティブは心配する必要がほとんどありません。それがあなたが気にしていることなら、スラッシュは受け入れられますが、バックスラッシュは受け入れられません。

5
abarnert

常にスラッシュを使用してください-それらはより多くのプラットフォームで動作します。バックスラッシュは技術的にはC++ 03で未定義の動作を引き起こします(標準では2.8/2)。

1
Alan Stokes

標準は#includeについてそれを言っています:

デリミタ間の指定のシーケンスで一意に識別されるヘッダーを実装定義の場所のシーケンスで検索し、ヘッダーのコンテンツ全体でそのディレクティブを置き換えます。場所の指定方法やヘッダーの識別方法は実装定義です。

最後の文に注意してください。

0
user2100815