4

私が維持しなければならないいくつかのレガシーコードでは、配列が (void *) 引数として渡されるときはいつでも & 演算子が配列名の前に置かれます

簡単な例を次に示します。

char val = 42;
char tab[10];
memcpy(&tab, &val, 1);

エラーや警告なしで gcc または clang でコンパイルされます。また、期待される結果も得られます。

この構文は合法ですか?

なぜこれが機能するのですか?

注: 通常、次の構文のいずれかを使用します。

memcpy(tab, &val, 1);
memcpy(&tab[0], &val, 1);

エピローグ:

追加のテストとして、(void*) の代わりに (char*) 引数を取る関数を使用しました。

clang でコンパイルしようとすると、次の警告が表示されます。

warning: incompatible pointer types passing 'char (*)[10]' to parameter of type 'char *' [-Wincompatible-pointer-types]

編集1:元の例では、タブは1要素のサイズで指定されました

一般化のために、サイズを 10 に変更しました。

編集2:回答で述べたように、memcpyは(void *)を取り、(char *)は取りません

4

1 に答える 1

10

memcpyのパラメータはタイプvoid*ではなく、タイプchar*です。ポインター型の引数 (関数ポインターを除く) は、暗黙的に に変換されvoid*ます。これは、 にのみ適用される特殊なルールですvoid*

宣言を考えると

char tab[1];

または のいずれtab&tabが への引数として有効ですmemcpy。これらは異なる型 (char*およびchar (*)[1]) のポインターとして評価されますが、どちらも同じメモリ位置を指しています。どちらに変換してもvoid*同じ値になります。

実際にchar*引数を必要とする関数の場合は、 のみtabが有効です。&tabは間違ったタイプです。printf(またはのような可変引数関数の場合scanf、コンパイラは型の不一致を検出できない場合があります。)

于 2013-10-19T18:53:49.813 に答える