1

私はプログラミングをより良くするためにcoreutilsソースコードを研究しています、そして私はこれらの行をbase64.cと他のもので見つけました:

while ((opt = getopt_long (argc, argv, "diw:", long_options, NULL)) != -1)
switch (opt)
{
// ... other stuff
  case_GETOPT_HELP_CHAR; // <- this especially

  case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
// .. other stuff again

system.hでこれを見つけるまで、これが一体何を意味するのかわかりませんでした。

#define case_GETOPT_HELP_CHAR           \
 case GETOPT_HELP_CHAR:         \
 usage (EXIT_SUCCESS);          \
 break;

こんなにたくさんの文で構成されたマクロを実際に作れるとは知りませんでした!マクロで非常に多くのステートメントを使用するのは危険ではありませんか、それともこれは私が学ぶべき良いコーディングスタイルですか?

編集:また、coreutilsで実際に使用されているマクロがたくさんあることに気づきました。私はC++のバックグラウンドを持っているので、少し混乱します。

#define STREQ(a, b) (strcmp (a, b) == 0)

たとえば、上記のこれは本当に必要ですか?これにより、コードの読み取りが難しくなり、infステートメントでSTREQUを実行するだけではあまり節約されません。

EDIT2:一方、ジェイのおかげで、私はこれがとても好きです:

 #define COMMAND(NAME)  { #NAME, NAME ## _command }

 struct command commands[] =
 {
   COMMAND (quit),
   COMMAND (help),
   ...
 };
4

4 に答える 4

1

適切に記述されている限り、このようなマクロを使用してもリスクはありません (そうでない場合、コンパイル エラーや予期しない動作が発生する可能性があります)。ただし、必要な場合以外は避けてください。コードが読みにくくなる傾向があります。

たとえば、マクロは常に呼び出されること#define foo() bar(); barになるため危険です (その場合、マクロ コードを でラップします) 。if(...) foo();bar()do{ ... }while(0)

于 2012-05-15T18:04:08.417 に答える
1

場合によります。マクロによってコード サイズが大幅に縮小されたり、1 か所だけの変更が大幅に簡単になったりする場合は、コード詩人の目には醜く見えることがあっても、ぜひ実行してください。

特定のケースでは、私は疑わしいです。まず、マクロはセミコロンで終了し、マクロの使用法も同様に終了するため、展開はセミコロンで終了します。そのうちの 1 つは null ステートメントです。いくつかのリントはそれらについて警告します。複数ステートメントのマクロの後にセミコロンを強制する正規の方法は次のとおりです。

#define FOO(x) do { statement(x); stmnt; } while (0)

しかし、これは、まあ、この場合は失敗しますcase。(偶然のしゃれ、へへ)。

次に、このマクロが実際にどこかで再利用されているかどうかはわかりません。そうでない場合は、洗練されたハッカーというよりも、コードの難読化だと思います。一方、それはsystem.h他のユーティリティにも含まれているように見えます。たとえば、「help」、「verbose」などに常に同じオプション char を使用するなど、多数の coreutils ユーティリティ間で一貫性を保つことにポイントがあります。

于 2012-05-15T18:14:42.327 に答える
0

リスクはありませんし、何の問題もありません。

こちらをお読みになり、Google を使用してマクロについての理解を深めてください。マクロについてある程度理解すると、いつ何を使用するかを決定できるようになります。

このstackoverflowリンクも確認してください。:) .

于 2012-05-15T18:02:10.250 に答える
0

回答をざっと読んでみればわかるように、それは好みの問題です。好きな人もいれば、嫌いな人もいます。
私はしません。

それに関する私の主な問題は、それを使用するコードが実際には C コードではないということです。したがって、それを読んで C を知っていても、まだ理解できません。

このような定義を不適切に使用すると、奇妙で​​デバッグが困難な問題が発生する可能性があります。コードを見ると、正しく見えますが、そうではありません。このcase_GETOPT_HELP_CHARマクロは、このようなエラーをあまり起こしにくいようです。case_GETOPT_VERSION_CHARパラメータを持つ は、より危険である可能性があります。

STREQはるかに優れたマクロです。それは物事をもう少し明確にしstrcmp(a,b)==0ます(私はいつもこれが混乱していると思います)。
経験則として、私は関数である可能性のあるマクロを好みます。STREQ必要に応じて関数として実装できますが、そうではありませんcase_GETOPT_HELP_CHAR

COMMANDは別の話です。それには何か醜いところがありますが、強力な正当化があります - それは繰り返しを取り除きます. マクロのトリックがなければ、コマンド名を 2 回繰り返さなければなりません。
一方、quit_command関数を見て、それがどこから呼び出されたのかを見つけようとするかわいそうな人を考えてみましょう。彼はソース全体でこの名前を検索できますが、見つかりません。

于 2012-05-15T18:46:48.503 に答える