「C言語/前処理指令」の版間の差分
削除された内容 追加された内容
M →前処理指令の基本: Fix タグ: 2017年版ソースエディター |
訳の手直し。s/ヘッダーファイル/ヘッダー/g タグ: 2017年版ソースエディター |
||
89 行
識別子(キーワードと同一のものを含む)は以下のように解釈されます。
;形式:<pre>
defined ''identifier''
</pre>または<pre>
defined ( ''identifier'' )
:条件付包含式( conditional inclusion expression )は、以下の形式の単項演算子式を含むことができます。<pre>▼
▲条件付包含式( conditional inclusion expression )は、以下の形式の単項演算子式を含むことができます。
__has_c_attribute ( ''pp-tokens'' )
</pre>こ
;セマンティクス
▲すべてのマクロ置換が行われた後に(制御式となる前処理トークンのリストに)残る各前処理トークンは、トークンの語彙形式でなければならない(6.4)。
:また、#ifdef、#ifndef、および定義済み条件付き包含演算子は、 __has_c_attribute を定義済みマクロの名前であるかのように扱うものとします。識別子 __has_c_attribute は、本節で言及されていないいかなる文脈にも登場してはなりません。▼
:以下の形式の前処理用ディレクティブ<pre>
▲また、#ifdef、#ifndef、および定義済み条件付き包含演算子は、 __has_c_attribute を定義済みマクロの名前であるかのように扱うものとします。識別子 __has_c_attribute は、本節で言及されていないいかなる文脈にも登場してはなりません。
#
▲ # elif ''constant-expression'' ''new-line'' ''group''<sub>opt</sub>
:評価の前に、制御する定数式となる前処理トークンのリスト内のマクロ呼び出しは、通常のテキストと同様に置き換えられます(定義された単項演算子によって変更されたマクロ名を除く)。この置換処理の結果として定義されたトークンが生成されたり、定義された単項演算子の使用がマクロ置換前の 2 つの指定された形式のうちの 1 つと一致しない場合、その動作は未定義です。マクロの展開とdefinedおよび__has_c_attribute単項演算子の評価によるすべての置き換えが行われた後、残りのすべての識別子(キーワードと語彙的に同一のものを含む)がpp-number 0に置き換えられ<ref>この未定義の識別子を 0 と解釈する挙動のため、識別子のミススペルがあたかも 0 を定義しているように見える事による発見困難なバグの原因になります。⇒ [[#未定義マクロの値]]</ref>、その後、各前処理トークンがトークンに変換されます。結果のトークンは、6.6の規則に従って評価される制御定数式を構成します。このトークンの変換と評価のために,すべての符号付き整数型とすべての符号なし整数型は,それぞれヘッダー<stdint.h>で定義されているintmax_t型とuintmax_t型と同じ表現を持っているかのように振る舞います。これには、文字定数の解釈も含まれており、エスケープシーケンスを実行文字セットのメンバーに変換する必要がある場合もあります。これらの文字定数の数値が、同一の文字定数が式の中(#ifや#elif指令の中を除く)に現れたときに得られる値と一致するかどうかは、実装で定義されます。また、1文字の文字定数が負の値を持つことができるかどうかは、実装で定義される。
▲制御する定数式の評価値がゼロでないかどうかをチェックします。
:以下の形式の前処理用ディレクティブ<pre>
# ifdef ''constant-expression'' ''new-line'' ''group''<sub>opt</sub>
# ifndef ''constant-expression'' ''new-line'' ''group''<sub>opt</sub>
</pre>は、識別子がマクロ名として現在定義されているかどうかをチェックする。これらの条件は、それぞれ''' #if defined identifier''' および '''#if !defined identifier''' と同じです。
: 各ディレクティブの条件は、順にチェックされます。入れ子になっている条件式のレベルを把握するために、指令は指令を決定する名前のみで処理され、残りの指令の前処理トークンは無視され、グループ内の他の前処理トークンも無視されます。制御条件が真(0以外)と評価された最初のグループだけが処理され、それ以降のグループはスキップされ、その制御指令はスキップされたグループに含まれているかのように処理されます。どの条件も真と評価されず、'''#else''' ディレクティブがある場合は、'''#else''' で制御されるグループが処理されます。'''#else''' ディレクティブがない場合は、'''#endif''' までのすべてのグループがスキップされます。
:例<source lang=c>
/* Fallback for compilers not yet implementing this feature. */
#ifndef __has_c_attribute
#define __has_c_attribute(x) 0
#endif /*
__has_c_attribute */
#if __has_c_attribute(fallthrough)
/* Standard attribute is available, use it. */
#define FALLTHROUGH [[fallthrough]]
#elif __has_c_attribute(vendor::fallthrough)
/* Vendor attribute is available, use it. */
#define FALLTHROUGH [[vendor::fallthrough]]
#else
/* Fallback implementation. */
#define F
</source>
前方参照:マクロの置換(6.10.3)、ソースファイルのインクルード(6.10.2)、最大の整数型
=== 未定義マクロの値 ===
137 ⟶ 141行目:
| page = 136, §6.10.2 ''Source file inclusion''
| publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}}</ref><ref>『JISX3010:2003』p.113「6.10.2 ソースファイル取り込み」</ref>。
;制約
:'''#include''' ディレクティブは、インプリメンテーションによって処理可能なヘッダーまたはソースファイルを特定するものです。
;セマンティクス
:以下の形式の前処理用ディレクティブ<pre>
# include < ''h-char-sequence'' > ''new-line''
</pre>この形式は、実装で定義されている一連の場所を検索して、 < と > の間の指定された順序で一意に識別されるヘッダーを探し、 そのディレクティブをヘッダーの内容全体で置き換える。どのように場所を指定するか、どのようにヘッダーを特定するかは、実装で定義されます。▼
:以下の形式の前処理用ディレクティブ<pre>
# include " ''q-char-sequence'' " ''new-line''
# include < ''h-char-sequence'' > ''new-line''
▲この形式は、実装で定義されている一連の場所を検索して、 < と > の間の指定された順序で一意に識別されるヘッダを探し、 そのディレクティブをヘッダの内容全体で置き換える。どのように場所を指定するか、どのようにヘッダを特定するかは、実装で定義されます。
:以下の形式の前処理用ディレクティブ<pre>
▲この形式は、" デリミタ "の間の指定された順序で特定されるソースファイルの内容全体で、その指示を置き換えます。指定されたソースファイルは、実装で定義された方法で検索されます。この検索がサポートされていない場合や、検索に失敗した場合は、次のようにヘッダーファイルが読まれたかのように再処理されます。
▲を、元の指令と同一の含まれたシーケンス(>文字があればそれも含む)に変更します<ref>標準ヘッダーファイル(stdio.hなど)を、<syntaxhighlight lang=c inline>#include "ヘッダーファイル名"</syntaxhighlight>の形式で取り込む事は、重大なセキュリティホールとなり得るので、厳に慎むべきです。</ref>。
# include ''pp-tokens'' ''new-line''
</pre>(前の
:;EXAMPLE 1 #include 前処理ディレクティブの最も一般的な使い方は以下の通りです。:<source lang=c>
▲(前の二つの形式のいずれにも一致しないもの)は許可されています。ディレクティブの include の後の前処理トークンは、通常のテキストと同様に処理されます。(現在マクロ名として定義されている各識別子は、その前処理トークンの置換リストで置換されます)。すべての置換後の指令は、前の2つの形式のいずれかに一致しなければならない。<と>の前処理トークンのペアまたは、"と"の前処理トークンを1つのヘッダー名の前処理トークンにまとめる方法は、実装で定義される。
#include <stdio.h>
#include "myprog.h"
</source>
:;EXAMPLE 2 マクロで置換された#includeディレクティブの例です。:<source lang=c>
#if VERSION == 1
#define INCFILE "vers1.h"
#elif VERSION == 2
#define INCFILE "vers2.h" // and so on
#else
#define INCFILE "versN.h"
#endif
#include INCFILE
</source>
前方参照:マクロの置き換え(6.10.3)
=== インクルードガード ===
インクルードガードとは、複数回ヘッダ
インクルードガードの記述は次のようになっている。
170 ⟶ 184行目:
#endif
</syntaxhighlight>
このヘッダ
2回目以降は「インクルードガード用の識別子」が定義されているため、
ソースコードが読み飛ばされる。
|