int main()
{
i/*nt*/a = 10;
return 0;
}
上記のコードがあり、トークンをカウントしたい場合、14トークンまたは13トークンになりますか?
変数名の中にコメントを書くことは有効ですか?あなたは、と仮定することができint i
、int a
、int ia
グローバルに定義されています。
int main()
{
i/*nt*/a = 10;
return 0;
}
上記のコードがあり、トークンをカウントしたい場合、14トークンまたは13トークンになりますか?
変数名の中にコメントを書くことは有効ですか?あなたは、と仮定することができint i
、int a
、int ia
グローバルに定義されています。
回答:
コメントは、プログラム変換1のフェーズ3で削除されます。各コメントは1つのスペース文字に置き換えられます。したがって、コメント/*nt*/
は間違いなくトークンではありません。
なしの場合はint
、main
、i
、a
またはreturn
プログラムを解析する生産、マクロを前処理として定義されている14個のトークン(いない13)。
int
main
(
)
{
i
a
=
10
;
return
0
;
}
ステートメントi
付きの型として定義されていない限り、C文法の規則と一致しないためtypedef
、構文エラーが発生しますi a
。
したがって、変数名内にコメントを書き込むことはできません。コメントは、識別子を2つの別々のトークンに分割します。これは、すべての前処理およびC言語トークン2に当てはまります。
ただし、単項演算子とそのオペランドの間、#
またはと前処理ディレクティブとその引数の間など、通常とは異なる場所にコメントを挿入できることに注意してください。
/**/#/**/include/**/<stdio.h>/**///////////////////////
/**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**////
/**/#/**/ifdef/**/STAT/**//////////////////////////////
/**/int/**/main/**/(/**/)/**/{/**//////////////////////
/**/int/**/a/**/=/**/+/**/1/**/;/**////////////////////
/**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/
/**/return/**/STAT/**/;/**/////////////////////////////
/**/}/**///////////////////////////////////////////////
/**/#/**/endif/**//////////////////////////////////////
ただし、上記のマクロ定義は、関数のようなマクロではなく、にSTAT
展開される通常のマクロを定義します( a ) - 1
。
他のトークンと同様に、変数名はエスケープされた改行によって分割できます。エスケープされた改行はシーケンスであるか、\
直後に改行が続きます。これらのシーケンスは、プログラム変換のフェーズ2でソースコードから削除されます。それらの主な目的は、複数行の長いマクロ定義を分割することです。
以下は、同じ14個のトークンを生成するコードフラグメント3です。
\
i\
nt\
ma\
in()
{\
i/\
*nt\
*/a \
= 10;
r\
et\
urn\
0;}
コードカラーライザーがスライスおよびダイシングされたキーワードとコメントを見逃したことに注意してください:)
1)この動作はANSI-C、別名C89で指定されています。一部の古代のコンパイラは、トークンの貼り付けをもたらす微妙に異なる動作をしていましたが、そのような特殊性は歴史的な関心のみです。
2)隣接する文字列定数がプログラム変換のフェーズ6で連結されるという事実を利用することにより、文字列定数内にコメントをほぼ挿入できます。 printf("Hello "/* my name is Luca */"world!\n");
3)このクリスマスツリーのプレゼンテーションスタイルは、実際のプログラムで使用するためのものではなく、Cの入力処理機能を悪用する方法を示しています。より精巧なトリックが国際難読化Cコードコンテストに勝ちました
\r
前にを含むエスケープされた改行を認識しないUNIXシステムでコンパイルエラーを引き起こし\n
ます。ただし、これが裏目にconst char *path = "C:\\"; // the default path is C:\
The path is "C:\"
コードの意味を持つよりも良いと思われるようなコメントを書くことは、末尾の改行に依存します。
語彙の観点からは、コメントは空白と同じです。
語彙要素に関するC標準のセクション6.4p3は次のように述べています。
...前処理トークンは空白で区切ることができます; これは、コメント(後述)、空白文字(スペース、水平タブ、改行、垂直タブ、およびフォームフィード)、あるいはその両方で構成されます。..。
より具体的には、コメントは単一のスペースに翻訳されます。これはセクション5.1.1.2p3で指定されています。
ソースファイルは、前処理トークンと空白文字のシーケンス(コメントを含む)に分解されます。ソースファイルは、部分的な前処理トークンまたは部分的なコメントで終わってはなりません。 各コメントは1つのスペース文字に置き換えられます。 改行文字は保持されます。改行以外の空白文字の空でない各シーケンスを保持するか、1つのスペース文字に置き換えるかは、実装によって定義されます。
これを説明するために、コードをプリプロセッサに渡すと、次のようになります。
int main()
{
i a = 10;
return 0;
}
したがって、空白のようなコメントは、トークンを区切るのに役立ちます。
これは、コードに13ではなく14のトークンが含まれることを意味します。
コードの形式を確認するだけです
int main()
{
int i/*nt*/a = 10;
return 0;
}
前処理後にあります。コンパイラに「-E」フラグgcc-E myscript.cを追加するだけで、次の結果が得られます。
e.sharaborin@landau:~$ gcc -E myscript.c
# 1 "myscript.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "myscript.c"
int main()
{
int i a = 10;
return 0;
}
そして明らかに、あなたは間違いがあると結論付けることができます。
はい、できます。コメントはコンパイラによってスキップされます。それらは変数に影響を与えません。コメントタグを終了することを忘れないでください。
i a
またはia
?
cpp -traditional
によって実装されているように、ANSI以前の「従来の」Cでは、に拡張されia = 10;
ます。