

宣言と定義の明確な違いはなんですか。  
例えば以下の例は、両方定義として考えていいのですか

[code]

    #define a 100
    #define b a
    
[/code]


CC BY-SA 3.0
2015-08-02T05:32:19.503
12941
2016-06-03T15:29:03.207
2015-08-05T06:43:49.030
4236
10762
question
c++ c preprocessor
宣言と定義の明確な違いはなんですか


宣言や定義はC++言語やC言語の概念ですが、`#define`文は[プリプロセッサー](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AA%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5)に対する構文であり、厳密にはC++言語やC言語ではありません。  
言語的な意味にほとんど関係なくマクロ展開されますので、当然、挙げられた例は定義でも宣言でもありません。


CC BY-SA 3.0
2015-08-02T05:42:23.773
12942
2015-08-02T05:42:23.773
4236
12941
answer


「宣言」「定義」は英語では"declaration"、"definition"です。  
本家stackoverflowにちょうど該当する質問があります。

  * [What is the difference between a definition and a declaration?](https://stackoverflow.com/questions/1410563/)

ここによると、簡単にいえばコンパイラが参照を解決するために必要な構文要素が「宣言」であり、リンカが参照をリンクさせるのに必要な構文要素が「定義」ということのようです。詳しくは本家の質問と回答を見てみてください。質問者さんが例で示したコードは、他の回答にある通り「プリプロセッサディレクティブ」であり、定義や宣言とはまた異なるものです。

定義と宣言の明らかな違いとしては、同じ識別子の「宣言」はコンパイル単位ごとに別々に存在できるのでひとつのプログラム中に複数回登場することがありますが、定義にはOne
Definition Ruleというルールがあり、ひとつの関数は単一の定義だけを持たなくてはならないという点です。


CC BY-SA 3.0
2015-08-02T12:57:14.357
12950
2015-08-02T13:13:44.637
2017-05-23T12:38:56.083
-1
10330
12941
answer


「宣言」は、コンパイラに、"この **名前** を使う" と教えるものです。「定義」は、 **名前とその中身**
を一緒に教えるものです。ですので、「定義」は、そのまま「宣言」ですが、「宣言」だからと言って「定義」とは限りません。

以下、説明のため、定義ではない宣言のことを「ただの宣言」と書くことにします。

ただの宣言は、中身についての情報を持たないので、中身を知らないとできないことをしようとすると、コンパイルエラーまたはリンクエラーになります。

[code]

    struct my_struct;   // ただの宣言
    
    my_struct * p;      // OK; ポインタは中身を知らなくても持てる
    my_struct s;        // コンパイルエラー; 中身が分からないと必要なメモリサイズが分からない
    p->a;               // コンパイルエラー; 本当に a がメンバーか不明
    
[/code]

関数の場合

[code]

    bool f1(int a);     // ただの宣言
    
    void f2(int b)
    {
        if(f1(b)) {     // OK; コンパイル時に中身を知らなくても呼べる
            // 何かの処理
        }
    }
    
[/code]

ですが、f1() が他のどこでも定義されていなければ、リンクエラーになります。

ただの宣言と定義の例を少し挙げてみます。

[code]

    int a;              // 定義
    extern int b;       // ただの宣言
    extern int c = 3;   // 定義; extern だが初期化されているので
    
    struct s1;          // ただの宣言
    struct s2 {
        int a;
        int b;
    };                  // 定義
    
    typedef int my_int; // ただの宣言
    
    int f(int a);       // ただの宣言
    int f(int a)
    {
        return a * a;
    }                   // f の再宣言かつ定義
    
[/code]

ちなみに `#define`
は、他の回答者の皆さんがおっしゃるとおり、宣言でも定義でもありません。コンパイラの本体が、ソースをコンパイルをする前に、プリプロセッサが処理するものだからです。


CC BY-SA 3.0
2015-08-02T19:11:38.433
12957
2015-08-02T19:11:38.433
3605
12941
answer


皆さんなんだかすっごく厳密だなぁ・・・まあオイラも人の事言えないけど。

ISO/IEC 14882:1998 を見た範囲で  
16.3 には 「マクロとして定義してある識別子」  
16.3.5 には「マクロ定義の有効範囲」  
16.8 には「あらかじめ定義されたマクロ名」  
と文言があるので `#define` は「マクロ定義」と呼ぶことができると思う。

マクロ宣言ってのは無いわけだけど、同じく 16.3-5  
「仮引数識別子は(snip)一意に宣言されていなければならない」  
ってことで「マクロ定義内における仮引数宣言」ってのは文言としてアリだと思う。

3.1 Declarations and definitions  
による、専門用語としての「宣言」「定義」なら皆様の解説のとおり。


CC BY-SA 3.0
2015-08-03T00:19:12.260
12960
2015-08-03T00:19:12.260
8589
12941
answer