C言語/記法

このページでは、C言語の記法に関する情報を網羅するよう心掛けました。
ISO/IEC 9899:2011(通称 C11)の §5.2.1 Character sets の冒頭を抄訳/引用します。
(C言語の処理系実装者は)2つの文字セットとそれに関連する照合順序( collating sequences )を定義しなければなりません。 ソース文字セット(the source character set; ソースファイルを記述するための文字セット)と、実行文字セット(the execution character set; 実行環境で解釈される文字セット)です。 それぞれのセットはさらに、基本文字セット( basic character set )と、拡張文字と呼ばれる0個以上の地域固有のメンバー(基本文字セットのメンバーではない)のセットに分けられます。 組み合わせたセットは、拡張文字セット( extended character set )とも呼ばれる。実行文字セットのメンバーの値は、実装で定義されます。
文字定数( character constant )や文字列リテラル( string literal )では、実行文字セットのメンバーは、ソース文字セットの対応するメンバーで表すか、バックスラッシュ( \ )に1つ以上の文字を続けたエスケープシーケンスで表します。
基本実行文字セット( basic execution character set )には、すべてのビットを0にしたバイト(ヌル文字)が存在し、文字列の終了に使用されます。
基本ソース文字セットと基本実行文字セットは、ともに次のものを有するものとします。
メンバー:
ソース基本文字セット及び実行基本文字セットの各メンバの表現は、1バイトに収まるものとします。ソース基本文字セット及び実行基本文字セットともに、上記の10進数のリストの0の後の各文字の値は、前の文字の値よりも1つ大きくなければならない。
ソースファイルでは、テキストの各行の終わりを示す何らかの方法がなければならない。本国際規格では、そのような行末表示を1つの改行文字のように扱う。基本実行文字セットには、アラート、バックスペース、キャリッジリターン、改行を表す制御文字がなければならない。
ソースファイルに他の文字が含まれている場合(識別子、文字定数、文字列リテラル、改行を除きます)。 識別子、文字定数、文字列リテラル、ヘッダー名、コメント、トークンに変換されない前処理トークンを除く)、動作は未定義です。
文字とは、上で定義したように、大文字または小文字のことです。
この国際規格では、この用語には他のアルファベットの文字である他の文字は含まれません。
国際文字名( universal character name )は、他のキャラクタに名前を付ける方法を提供します。 前方参照:国際文字名(§6.4.3)、文字定数(§6.4.4.4)、前処理ディレクティブ(§6.10)、文字列リテラル(§6.4.5)、コメント(§6.4.9)、文字列(§7.1.1)。

トライグラフシーケンスは、ISO/IEC 9899:2023(通称 C23)で削除される予定です。
ISO/IEC 9899:2011(通称 C11)の §5.2.1.1 Trigraph sequences の冒頭を抄訳/引用します。
他の処理を行う前に、次のような3つの文字の並び(トライグラフ・シーケンス=3文字表記と呼ばれる)のうちの1つが出現するたびに、対応する1つの文字に置き換えられます。
これ以外の3文字表記は存在しません。 上に掲げた3文字表記に当てはまるらない ? は、置き換えない。
3文字表記は、7ビットUS ASCII符号集合の部分集合であるISO/IEC646で規定する普遍符号集合に定義がない文字の入力を可能にします。
3文字表記に一致する文字列を表記したい場合、「?」の代わりに逆斜線表記(エスケープシーケンス)の「\?」を用いるとよい。 現在、3文字表記はほとんど使われず、言語処理系によっては、デフォルトで無効にであったり、実装されていなかったり、外部のプロプロセッサとして実装されていたりします。
この部分は、ISO/IEC 9899:1999(C99;JIS X 3010:2003の翻訳元)とISO/IEC 9899:2011(C11)で異なる部分で、JIS X 3010:2003『プログラム言語 C』では、
次に示す左側の三つの文字の並び[3文字表記(trigraph sequence(12))という。]がソースファイルの中にある場合,その三つの文字の並びを同じ行の右側の対応する1文字に置き換える。
これら以外の3文字表記は,存在しない。 上に掲げた3文字表記の始まりとならない?は,置き換えない。
となっており、修正後のC11では前処理であることが強調されています。
ISO/IEC 9899:2011(通称 C11)の §5.2.1.2 Multibyte characters の冒頭を抄訳/引用します。
ソース文字セットには、拡張文字セットのメンバーを表すために使用されるマルチバイト文字が含まれることがあります。 実行文字セットは、マルチバイト文字を含むことができますが、これらの文字はソース文字セットと同じエンコーディングである必要はありません。
両方の文字セットについて、次のことを守らなければならない。
標準では上記のように、文字集合と符号化方式の両方を規定していないので移植性や相互運用性については、プログラマが工夫することとなります。
JISCでは、字句(token)は,翻訳フェーズ(7)及び(8)において言語の最小の字句的な単位とする。となっていますが定義が循環していて意味不明です.。
原文では、A token is the minimal lexical element of the language in translation phases 7 and 8.とあり、「トークンとは、翻訳フェーズ(7)および(8)において、言語の最小の語彙要素のことです。」と訳すことが出来ます。
字句の種類は、キーワード、識別子、定数、文字列リテラルおよび区切り子です。
キーワードとは特定の機能のために予約された字句であり、その他の機能のためには使用できない。キーワードとは次のいずれかです。 。
識別子とは、オブジェクト、関数、構造体・共用体・列挙体のタグまたはメンバー、typedef名、ラベル名、マクロ名、マクロ仮引数のいずれか一つを表します。 同じ識別子でも、プログラム中の異なる時点では異なる実体を表すことがあります。 列挙型のメンバーは列挙定数と呼ばれます。 マクロ名とマクロ仮引数パラメータについては、ここでは説明しません。プログラム翻訳の意味論的な段階の前に、ソースファイル内でマクロ名が出現すると、それは マクロ定義を構成する前処理のトークンシーケンスに置き換えられるからです。
識別子とは、1つ以上のエンティティを指定する非桁の文字(アンダースコア_、小文字と大文字のラテン文字、その他の文字を含む)と数字のシーケンスです。小文字と大文字は区別されます。 識別子の最大長には特に制限はありません。 識別子に含まれる各汎用文字名は、ISO/IEC 10646(UCS)における符号化がD.1.71に規定された範囲のいずれかに該当する文字を指定しなければならない)。 初期文字は、符号化がD.2に規定された範囲のいずれかに該当する文字を指定する汎用文字名であってはならない。 実装では、基本ソース文字セットに含まれないマルチバイト文字を識別子に使用することができる。
ISO/IEC 9899:2011(通称 C11)の §7.1.3 Reserved identifiers を抄訳/引用します。
各ヘッダーは、関連する(仕様書の)小節に記載されているすべての識別子を宣言または定義し、オプションとして、関連する将来のライブラリの方向性の小節に記載されている識別子や、任意の用途またはファイルスコープの識別子として常に予約されている識別子を宣言または定義します
その他の識別子は予約されていません。7.1.4項で許可されている場合を除き、予約されている文脈で識別子を宣言・定義した場合や、予約されている識別子をマクロ名として定義した場合、その動作は未定義です。
プログラムが、上記の第1グループの識別子のマクロ定義を(#undefで)削除した場合、その動作は未定義である。
この定義から、以下は予約済み識別子です。

識別子 __func__ は、翻訳者(translator)によって以下のように暗黙的に宣言されなければなりません。 各関数定義の開始波括弧の直後に、次のような宣言があるように振る舞います。
ここで、function-nameは字句解析的包含( lexically-enclosing )された関数の名前です。
ISO/IEC 9899:2011(通称 C11)の §6.4.3 Universal character names(JIS Cでは国際文字名と和訳) の冒頭を抄訳/引用します。
定数( Constraints )とはプログラム実行時に一定の値しかもたない数です。 変数の値がプログラム実行中に変更される場合もあるのに対して、定数の値はプログラム実行中を通して一定です。
定数には整数定数、浮動小数点定数、列挙定数、文字定数があります。
文字定数に前置する L, U, u については、規格の版ごとに定義がまちまちで、C23では(文字列リテラルと同じ様に)encoding-prefix とされそうですが、2021年8月時点の最新の C17 では文字定数と文字列リテラルでは(文字定数だけu8が使えないなど)不統一です。
整数定数に接尾辞を付けることで、符号の有無と型を指定できます。
2 と 3 は併用でき、前後を問いません(168UL と 168LU は同じ意味)
浮動小数点定数に接尾辞を付けることで、その型を指定できます。 浮動小数点定数の型は、接尾辞なしで型double、接尾辞f又はFで型float、l又はLで型long doubleです。
文字列リテラル( String literals )には、単純文字列リテラルとワイド文字列リテラルがあります。
C言語では文字列は(NULL文字で終端された)文字の配列として扱われる。
区切り子とは次のいずれかである。
区切り子とは、独立した構文的及び意味的な機能を持つ記号である。 何らかの操作を行うとき、それを演算子と呼ぶ。また演算子が操作を行う対象をオペランドと呼ぶ。
次の6つの2文字の字句は、2文字表記( digraphs )と呼ばれます。
前の6つの字句は、次の6つの字句と同じである。
ヘッダー名とは、#include前処理指令で読み込まれるファイル名を指します。 ヘッダー名には「'、\、"、//、/*」に表れた時、その動作は未定義です。
前処理数(Preprocessing numbers; Syntaxでは pp-number)
N2176 C17 ballot ISO/IEC 9899:2017 §6.4.8 Preprocessing numbers:前処理数から引用/抄訳.
上記のように前処理数の解析は、後にくる厳格な構文解析を行うわけではなくもっぱら字句解析によります。
の様なコードで前処理数が問題になります。一見すると 0xfe に 0x2 を足す様に見えますが、 0xfe+0x2 が前処理数の定義に合致してしまうので、[翻訳フェーズ(7)に数(らしきもの)として渡されてしましますが、16進浮動小数点定数の構文には合致しないので
の様なエラーになります。 この場合は、
とスペースを補うことで回避できます。
文字定数、文字列リテラル、コメントの中を除き、/* は注釈( Comments; コメント)の開始を表します。 このようなコメントの内容は、マルチバイト文字を特定するためと、コメントを終了させる文字 */ を見つけるためにのみ検査されます。 /* . . . */ コメントはネストできません。
文字定数、文字列リテラル、コメントの中を除き、// は次の改行文字までのすべてのマルチバイト文字を含むコメントを表します。
C99より前にも、「//」で始まる一行コメントは言語処理系によって独自拡張として実装されてましたが、C99で正式に標準規格に取り入れられました。
文( Statements )は、ラベル付き文、複合文、式文、選択文、繰返し文、分岐文のいずれかです(宣言( declaration )は文ではありません)。
ラベル付き文( Labeled statements )は、goto 文の飛び先としてのラベルの他、swicth文の case節 及び default節を含みます。 すべてのステートメントの前には、識別子をラベル名として宣言するプレフィックスを付けることができます。 ラベルはそれ自体、制御の流れを変えるものではなく、ラベルを越えても制御の流れは妨げられません。
複合文( Compound statement )は、ブロックのことです。 { と } の間に任意個の宣言と文を含むことが出来ます。 。 C89までのブロックの前方に宣言、後方に文を置く制限はC99でなくなり、(C++のように)文より後に宣言を置くことも可能になりました。
式文( Expression and null statements )の中の式は、その副作用としてvoid式として評価されます 。 セミコロンだけで構成される文(null文)は、何の処理も行いません。
選択文( Selection statements ) は、制御式の値に応じて、一連の文の中から選択します 。 選択文は、そのスコープが周囲のブロックのスコープの厳密なサブセットであるブロックです。 関連するサブステートメントもまた、選択ステートメントのスコープの厳密なサブセットをスコープとするブロックです。
繰り返し文( Iteration statements、反復文とも)の制御式は、スカラー型でなければなりません 。 for文の宣言部では、記憶クラスが auto または register であるオブジェクトの識別子のみ宣言が可能です。 繰り返し文は、ループ本体と呼ばれる文を、制御式の比較が0になるまで繰り返し実行させます。 繰り返しは、ループ本体が繰り返し文から入力されたか、ジャンプで入力されたかにかかわらず発生します。 繰り返し文のブロックのスコープは、そのブロックを囲むブロックのスコープの厳密なサブセットであるブロックです。 ループ本体もまた、繰り返し文のスコープの厳密なサブセットであるブロックです。
分岐文( Jump statements )は、無条件で別の場所にジャンプします 。