2

Keil C51 コンパイラを使用して 8051 マイクロコントローラをプログラムしています。なんらかの理由でコードが実行されませんでした。バグを突き止めることはできましたが、まだ理解に苦慮しています。他のコードと比較して、最初のコードが間違っているのはなぜですか? コンパイラがエラーをスローしなかったことは注目に値します。コードはマイクロコントローラー上で開始さえしませんでした。

不正なコード:

file1.h

extern STRUCT_TYPEDEF array_var[];

file2.c

// Global variable initialization
STRUCT_TYPEDEF array_var[] = some_struct.array2_var;

これらを次のように変更した後:

file1.h

extern STRUCT_TYPEDEF *array_var;

file2.c

// Global variable initialization
STRUCT_TYPEDEF *array_var = &some_struct.array2_var[0];

それは働き始めました。

また、コードのこの部分は「array_var[0].property = ...」などの関数でのみ参照されていましたが、これらの関数はいずれもアプリケーションから呼び出されていませんでした。

some_struct 変数は、さらに別のモジュールで宣言されています。

なぜそのように振る舞うことができたのでしょうか?[] と * の違いはありますか?

EDIT1: ポインターと配列は別物だと言われていますが、「[]」構文は「*」とどう違うのでしょうか? 角括弧が空の場合(関数の引数の場合と同様)、コンパイラはそれをポインターに変換するだけだと思いました。また、配列を提供すると、最初の要素のアドレスが得られると思いました。

現在、誰もがポインターと配列が異なると言っていますが、それらの正確な違いに関する情報は見つかりません。配列を最初の要素へのポインターではなく右辺値として指定すると、コンパイラーはそれをどのように認識しますか?

4

2 に答える 2

7

STRUCT_TYPEDEF array_var[] = some_struct.array2_var;

宣言で配列を初期化する有効な方法ではありません。配列初期化子は、次のような中括弧で囲まれた初期化子のリストでなければなりません。

T arr[] = { init1, init2, init3 };

配列を別の配列1で初期化することはできません。また、次の方法である配列を別の配列に割り当てることもできません。

T foo[] = { /* list of initializers */ }
T bar[] = foo; // not allowed
T bar[N];
...
bar = foo; // also not allowed

some_struct.array2_varの内容をにコピーする場合はarray_var、次のようなライブラリ関数を使用する必要がありますmemcpy

memcpy( array_var, some_struct.array2_var, sizeof some_struct.array2_var );

array_varサイズも宣言する必要があります。使用したい場合は、不完全なままにすることはできません。必要なサイズが事前にわかっている場合は、次のように簡単です。

STRUCT_TYPEDEF array_var[SIZE];
...
mempcy( array_var, some_struct.array2_var );

必要なサイズが事前にわからない場合は、可変長配列として宣言する必要があります (ファイル スコープにある必要がある場合や、static保存期間がある場合は機能しません)。 )、またはメモリを動的に宣言できます。

STRUCT_TYPEDEF *array_var = NULL;
...
array_var = malloc( sizeof some_struct.array2_var );
if ( array_var )
{
  memcpy( array_var, some_struct.array2_var, sizeof some_struct.array2_var );
}

some_struct.array2_varこれはすべて、次のように宣言された配列であると想定しています

STRUCT_TYPEDEF array2_var[SIZE]; 

それが単なるポインターでもある場合は、別の方法で配列サイズを追跡する必要があります。

編集

の最初の要素array_varを単純に指し示す場合some_struct.array2_varは、次のようにします。

STRUCT_TYPEDEF *array_var = some_struct.array2_var;

sizeofまたは 単項演算子のオペランドである場合を除き、&型 "N 要素配列T" の式は型 "pointer to T" の式に変換 ("decay") され、式の値は配列の最初の要素のアドレス。上記のコードは、

STRUCT_TYPEDEF *array_var = &some_struct.array2_var[0];


  1. char message[] = "Hello";;などの文字列リテラルを除きます。文字列リテラル"Hello"は配列式ですが、言語はそれを特殊なケースとして扱います。

于 2016-05-19T17:30:52.680 に答える