#define
sなどは通常インデントされないことを知っています。どうして?
現時点では、#define
s、#ifdef
s、#else
s、#endif
sなどの恐ろしい混合物があるコードで作業しています。これらはすべて通常のCと混ざり合っています。コード。 #define
sをインデントしないと、読みにくくなります。そして、インデントされたコードとインデントされていない#define
sの混在は悪夢です。
#define
sをインデントしないことの利点は何ですか?インデントするとインデントが悪い人になりますか?これははるかに優れていませんか?
#ifdef SDCC
#if DEBUGGING == 1
#if defined (pic18f2480)
#define FLASH_MEMORY_END 0x3DC0
#Elif defined (pic18f2580)
#define FLASH_MEMORY_END 0x7DC0
#else
#error "Can't set up flash memory end!"
#endif
#else
#if defined (pic18f2480)
#define FLASH_MEMORY_END 0x4000
#Elif defined (pic18f2580)
#define FLASH_MEMORY_END 0x8000
#else
#error "Can't set up flash memory end!"
#endif
#endif
#else
#if DEBUGGING == 1
#define FLASH_MEMORY_END 0x7DC0
#else
#define FLASH_MEMORY_END 0x8000
#endif
#endif
ANSI C以前のプリプロセッサでは、行の先頭と「#」文字の間にスペースを入れられませんでした。先頭の「#」は常に最初の列に配置する必要がありました。
最近、ANSI以前のCコンパイラは存在しません。好みのスタイル(「#」の前のスペース、または「#」と識別子の間のスペース)を使用します。
既に述べたように、一部のPre-ANSIコンパイラーは、#を行の最初の文字にする必要がありましたが、それに付加するdeプリプロセッサーディレクティブを必要としなかったため、このようにインデントが行われました。
#ifdef SDCC
# if DEBUGGING == 1
# if defined (pic18f2480)
# define FLASH_MEMORY_END 0x3DC0
# Elif defined (pic18f2580)
# define FLASH_MEMORY_END 0x7DC0
# else
# error "Can't set up flash memory end!"
# endif
# else
# if defined (pic18f2480)
# define FLASH_MEMORY_END 0x4000
# Elif defined (pic18f2580)
# define FLASH_MEMORY_END 0x8000
# else
# error "Can't set up flash memory end!"
# endif
# endif
#else
# if DEBUGGING == 1
# define FLASH_MEMORY_END 0x7DC0
# else
# define FLASH_MEMORY_END 0x8000
# endif
#endif
古いUnixヘッダーでよくこのスタイルを見てきましたが、このようなコードでは構文の色付けが失敗することが多いため、嫌いです。プリプロセッサディレクティブに目立つ色を使用して、それらが目立つようにします(メタレベルであるため、通常のコードフローの一部ではありません)。 SOがシーケンスを便利な方法で色付けしないこともわかります。
プリプロセッサディレクティブの解析に関して、C99標準(およびその前のC89標準)は、コンパイラによって論理的に実行される一連の操作について明確でした。特に、このコードは次のことを意味すると考えています。
/* */ # /* */ include /* */ <stdio.h> /* */
以下と同等です:
#include <stdio.h>
良くも悪くも、「-std = c89 -pedantic」を指定したGCC 3.4.4は、コメントが含まれる行を受け入れます。私はそれをスタイルとして主張しているのではありません-ちょっとの間ではありません(恐ろしいです)。可能だと思う。
ISO/IEC 9899:1999セクション5.1.1.2の翻訳段階には次のように書かれています:
[3文字表記を含む文字マッピング]
[ラインスプライシング-バックスラッシュ改行の削除]
ソースファイルは、前処理トークンと空白文字のシーケンス(コメントを含む)に分解されます。ソースファイルは、部分的な前処理トークンまたは部分的なコメントで終わってはなりません。各コメントは1つのスペース文字に置き換えられます。改行文字は保持されます。改行以外の空白文字の空でない各シーケンスを保持するか、1つのスペース文字で置き換えるかは、実装によって定義されます。
前処理指令が実行され、マクロ呼び出しが展開されます、[...]
セクション6.10の前処理指令には次のように書かれています:
前処理ディレクティブは、(変換フェーズ4の開始時に)ソースファイルの最初の文字(オプションで改行文字を含まない空白の後)である#前処理トークンで始まる一連の前処理トークンで構成されます。少なくとも1つの改行文字を含む空白に続き、次の改行文字で終了します。
考えられる唯一の論争は、括弧付きの表現「(変換フェーズ4の開始時)」です。これは、フェーズ4の終了までスペースで置き換えられないため、ハッシュの前のコメントが存在しないことを意味します。
他の人が述べたように、先行標準のCプリプロセッサは多くの点で一様に振る舞いませんでした。 。
コメントが分析される前にバックスラッシュと改行が削除されることは注目に値します。したがって、//
コメントをバックスラッシュで終了しないでください。
なぜそれほど一般的ではないのかわかりません。確かに、プリプロセッサディレクティブをインデントしたい場合があります。
私の邪魔をし続ける(そして時々私は試してみるのをやめるように説得する)ことの一つは、多くの、またはほとんどの編集者/ IDEがわずかな挑発で1列目にディレクティブを投げるということです。それは地獄として迷惑です。
最近、これは主にスタイルの選択だと思います。 I 思考遠い過去のある時点で、すべてのコンパイラーがプリプロセッサー定義のインデントの概念をサポートしているわけではありませんでした。私はいくつかの調査を行ったが、その主張を裏付けることができなかった。しかし、いずれにしても、最新のコンパイラーはすべて、プリプロセッサーマクロをインデントするという考え方をサポートしているようです。私はCまたはC++標準のコピーを持っていないので、これが標準的な動作であるかどうかはわかりません。
良いスタイルかどうかについて。個人的に、私はそれらをすべて左に保つというアイデアが好きです。それらを探す一貫した場所を提供します。ネストされたマクロが非常に多い場合、うんざりする可能性があります。しかし、それらをインデントすると、最終的にはさらに奇妙なコードになります。
#if COND1
void foo() {
#if COND2
int i;
#if COND3
i = someFunction()
cout << i << eol;
#endif
#endif
}
#endif
この例では、ネストされたディレクティブの複雑な構造があるため、インデントを使用して明確にすることが適切な場合があります。
個人的には、これらのディレクティブは他のコードとは別に動作するため、ほとんどの場合インデントしないようにすると便利だと思います。 #ifdefなどのディレクティブは、コンパイラがコードを認識する前にプリプロセッサによって処理されるため、#ifdefディレクティブの後のコードブロックはcompiledでさえない場合があります。
ディレクティブをコードの他の部分から視覚的に分離することは、コードに散在している場合に重要です(指定した例のように、ディレクティブの専用ブロックではありません)。
現在、#defines、#ifdefs、#elses、#endifs、#etcの恐ろしい混合物があるコードで作業しています。これらはすべて通常のCコードとよく混ざり合っています。 #definesをインデントしないと読みにくくなります。そして、インデントされたコードとインデントされていない#definesの混在は悪夢です。
一般的な解決策は、ディレクティブにコメントすることです。これにより、ディレクティブが何を参照しているかを簡単に知ることができます。
#ifdef FOO
/* a lot of code */
#endif /* FOO */
#ifndef FOO
/* a lot of code */
#endif /* not FOO */