5

main.c で foo.c の変数 a を使用したいので、次のように記述します。

foo.c
#include <stdio.h>

int a[] = {3, 2};

void foo()
{
    printf("foo\taddress of a:%x\n", a);
    printf("foo\tvalue of a[0]:%x\n", a[0]);
}

main.c
#include <stdio.h>

extern int *a;

int main(void)
{
    foo();
    printf("main\taddress of a : %x\n", a);
    printf("main\tvalue of a[0] : %x\n", a[0]);

    return 0;
}

および結果出力:

foo address of a:804a014
foo value of a[0]:3
main    address of a : 3
Segmentation fault (core dumped)

なぜ?

4

2 に答える 2

8

のタイプaint[2]、ではありませんint*。で再試行してください

extern int a[2];

Cコンパイラは、ソースファイル間でタイプチェックを行うことはできません。したがって、と言うint* aと、コンパイラはあなたが真実を言っていると想定し、ポインタセマンティクスを使用し、コンパイラエラーを発行しません。

配列とポインタには微妙な違いがあります。32ビットシステムを想定しましょう。次に、「a」のコンテンツは次のように配布されます。

    a
0x1000x1040x108←アドレス
    + ----------- + ---------- +
    | 3 | 2 | ←コンテンツ
    + ----------- + ---------- +

a配列の場合、

  • 式の値は、aのアドレスに変換されますa。したがって、を印刷aすると、そのアドレス、つまり「0x100」が取得されます。
  • Cでの操作a[n]は、と同等です*(a + n)。つまり、アドレスan単位単位で進めてから、逆参照してコンテンツを取得します。したがって、は、コンテンツを0x100、つまり「3」で返すa[0]と同等です。*0x100

aポインタの場合、

  • の「値」aは、指定されたアドレスのコンテンツです。実際、これは標準であり、配列型は特殊なケースです。したがって、を印刷aすると、そのアドレス、つまり「3」にコンテンツが表示されます。
  • 操作a[n]はまだ*(a + n)です。したがって、はとa[0]同等*3であり、アドレス「3」が無効であるため、セグメンテーション違反が発生します。
于 2012-06-23T08:30:27.800 に答える
1

異なる翻訳単位で宣言されたオブジェクトには、一貫した型を使用する必要があります。

が与えられint a[] = {2, 3};た場合、宣言extern int a[];またはextern int a[2]; extern int *a;互換性がありますが、ポインターと配列は完全に別の型であるため互換性はありません。

&配列に関する特別な点の 1 つは、配列の名前が「アドレス」(単項) またはのオペランドとして以外の式のコンテキストに表示される場合sizeof、最初の要素へのポインターに自動的に変換されることです。これにより、配列とポインター間の構文の互換性が提供されますが、それらは同じ型ではありません。

コメント付きの例として、これら 2 つの関数を検討してください。a式は、最初の関数の 2 番目 (技術的には 3 番目) で最初の要素へのポインターに変換されますが、それが のオペランドでprintfある最初の関数では変換されないことに注意してください。printf&

#include <stdio.h>

void print_array_info(void)
{
    extern int a[];
    printf("address of a:  %p\n", (void*) &a);   // prints address of a
    printf(" converted a:  %p\n", (void*) a);    // prints address of a[0]
    printf("value of a[0]: %x\n", a[0]);         // prints value of a
}

void print_pointer_info(void) {
    extern int a[];
    int *b = a; // == &a[0]

    printf("address of b:  %p\n", (void*) &b);  // prints address of b
    printf("  value of b:  %p\n", (void*) b);   // prints value of b (== &a[0])
    printf("value of b[0]: %x\n", b[0]);        // prints value of b[0] (== a[0])
}

%pポインターを出力し、明示的に にキャストするために使用することに注意してくださいvoid*

于 2012-06-23T09:22:30.943 に答える