2017-07-15 11 views
4

構造体エイリアスがバイナリにコンパイルされる方法を理解しようとしています。私は、a *とa *の両方でエイリアスを持つと、別のバイナリ(shasumを使ってチェックされている)になります。たとえば、次のような構造を与えられた:Cの構造体エイリアスのコンパイル方法の理解

typedef struct __foobar { 
    int a; 
    int b; 
} *pfoobar_t, foobar_t; 

は、どのようにC標準およびコンパイラの観点から異なる次の変数宣言です:

const pfoobar_t my_var; 
const foobar_t *my_var; 
foobar_t const *my_var; 

事前にありがとうございます。

+0

相違点を説明する2つの完全な例を提供できますか? –

答えて

3

const pfoobar_t my_var; 

const foobar_t *my_var; 

の違いは最初のものが第二つconstオブジェクトへのポインタであることmy_varを宣言し、一方、constことがmy_var自体を宣言することです。

const変数を初期化する必要がある(変更できないため)ファイルスコープ以外は最初のものが正しくありません。ファイルスコープでは、変数はNULLに初期化されます。それを変更することはできないので、その使用は定数NULLに置き換えることができます。

2番目のケースでは、変数自体を変更することができるため、初期化されていないかどうかは関係ありません。しかし、一度それがstruct __foobarを指すようにされると、そのオブジェクトをポインタで修正することはできません。

3番目の宣言は2番目の宣言と同じです。最初のものは、ちなみに

foobar_t *const my_var; 

が書き込まれていることができ、(例えばstruct __foobarのような)2つのアンダースコアで始まる識別子は標準ライブラリ(または他の実装の詳細)による使用のために予約されており、プログラムの中で使用すべきではありません。

+0

最初と3番目が同じ場合、生成されるバイナリのShasumが異なるのはなぜですか? @Slagathor。 – slagathor

+0

私は2番目と3番目のものは同じだと言った。最初は違う。 – rici

+0

あなたがしたこと。私の間違い。あなたが持っていた最後のいくつかのコメントを速く読んで、混合してください。 – slagathor

1

構造体は単純にメモリの圧縮された部分です。例、32ビットアーキテクチャのint a; int b;は、8バイト構造(2 x 4バイト)になります。

割り付けられていない構造体(例えば9バイト)が割り当てられますが、割り当てられたメモリ領域は(12バイト、sub $esp, 12)配置されます。

あなたはコンパイラが異なった反応をすることを見ることができ、そしてそれらの割り当てがconstディレクティブを使用することによって、特に異なること:あなたが試す

typedef struct __foobar { 
    int a; 
    int b; 
} *pfoobar_t, foobar_t; 

は、以下の構造を考えると

#include <stdio.h> 

int main(){ 
    foobar_t var; 
    const pfoobar_t my_var = &var; 
    my_var->a = 3; 
    printf("%d\n", my_var->a); 
} 

コンパイルして問題なく実行します。それはコンパイルされません

#include <stdio.h> 

int main(){ 
    foobar_t var; 
    const foobar_t *my_var; 
    my_var->a = 3; 
    printf("%d\n", my_var->a); 
} 

:今のコードを変更する

const.c: In function ‘main’: 
const.c:13:3: error: assignment of member ‘a’ in read-only object 
    my_var->a = 3; 

静的オブジェクトは、バイナリの専用部分に格納されているので、あなたの異なった宣言はELF形式の形状を変更します。