web-dev-qa-db-ja.com

main関数内に「includeディレクティブ」を配置するのは悪いことですか?

それは常にinclude directivesはスクリプトの先頭に配置する必要があります。主な理由は、スクリプト全体で関数を使用できるようにするためです。この事実に関係なく、include directive必要なメイン関数内?

例えば、

#include <stdio.h>
int main() {
#include <mysql.h>
}

の代わりに

#include <mysql.h>
#include <stdio.h>
int main() {
}

パフォーマンスやコンパイル済みファイルのサイズに違いを見つけることはできませんでしたが、単純なスクリプトでこの事実を判断することは困難です。この非標準的なアプローチを回避するために、何らかの効果や欠点、または何らかの理由があるのでしょうか。

5
Googlebot

インクルードファイル内のコードによって異なります。

Main()内に<stdio.h>の#includeを入れてみましたか?システムに標準ライブラリがどのように実装されているかによっては、コンパイルできない場合もあります。ヘッダーファイルには、関数宣言だけでなく関数定義も含めることができます。標準Cはネストされた関数をサポートしていません。

ヘッダーファイルに関数と変数の宣言が含まれている場合、それらをmain()の本体内に配置すると、スコープが制限されます。

ヘッダーファイルにプリプロセッサマクロのみが含まれている場合は機能する可能性がありますが、予期しない場所にインクルードを不当に移動すると、他のすべてのCプログラマーを困らせます。 Cではコーディングの基準が特に重要です。なぜなら、Cはユーザーを混乱させるのを防ぐための保護手段がほとんどないからです。

13

Cプログラマーは、全体として#includeディレクティブをファイルの先頭ににします。重要な利点なしに混乱を招くリスクがあるのはなぜですか。

I know where I'm going. Really, I do.

11
Robert Harvey

ヘッダーファイルで検出される可能性のある事柄を検討してください。

  • プリプロセッサマクロ。これらは、ヘッダーを含む#includeファイルの最後まで.cから利用できます。プリプロセッサマクロはCブロックのスコープ(中かっこ)を考慮しないため、ヘッダーが関数内にある場合でも、マクロはブロックの終了後も使用できます。
  • 型、変数、関数の宣言。それらのスコープは、#includeディレクティブが配置されているブロックになります。通常は問題ありません。ただし、機能するのは1回だけです。ほとんどすべてのインクルードファイルにはヘッダーガードが含まれているため、ファイルが複数回インクルードされた場合(ヘッダーが他のヘッダーを必要とすることが原因で発生することが多い)、そのコンテンツは1回だけ処理されます。したがって、複数の関数で同じヘッダーを#includeした場合、宣言は初めて利用できるようになります。
  • 関数(または変数ですが、ヘッダーでは非常にまれです)の定義。ヘッダーには、コンパイラーがインライン化できる小さなstatic関数が含まれることがあります。 #includeディレクティブが関数内にある場合、これらはコンパイルに失敗します。これは、(一部のコンパイラー拡張を除いて)別の関数内に関数を定義できないためです。

したがって、スタイルの問題だけではありません。関数内の#includeは、通常は機能しません。

#includeディレクティブをファイルスコープのどこにでも(つまり、関数の外に)置くことができ、技術的に大きな悪影響はありません。それが定義するエンティティは、#include行の下でのみ使用できます。それは主にスタイルの問題ですが、それは異常で無意味であるため、メンテナを混乱させます。ヘッダーで宣言されたものと同じ名前の変数または関数を定義すると、混乱を招く可能性もあります。これは、不一致がヘッダー(または含まれるヘッダーに含まれるヘッダー)で報告されるためです。 )、コード内ではなく、奇妙な実装固有の構文を使用している可能性があります。

そう、それは悪いことです。すべての#includeディレクティブをファイルの先頭近くにグループ化します。コメントや、実装のドキュメントで指示されている場合は#pragmaまたは#defineを使用します。

本当に非常に悪い!

その理由は、多くのCヘッダーファイルに次のようなマクロがたくさん含まれているためです。--

 #if !defined(MYSTUFF_INCLUDED)          /* File not yet included? */
   #define MYSTUFF_INCLUDED                /* Show file now included */
   int variable1;
   int variable2;
 #endif

マクロ変数には「ファイル」スコープがありますが、関数内に「#INCLUDE」を含めると、マクロ変数内に定義された変数はすべて関数スコープになります。

そう

    #include <stdio.h>
    int main() {
        #include <mysql.h>
        call doSql();
     }
     int doSql () {
        #include <mysql.h>
        .....
     }

マクロ変数MYSQLはすでに定義されており、2番目のINCLUDEは何も定義しないため、コンパイルされません。

4
James Anderson

長いものは短い...できるだけ避けてください絶対に必要な場合にのみ行ってください(必要な場合は考えられません)クリーンで保守可能なコード。

0
Farouk Jouti