以下は本の抜粋ですCプログラミングJust FAQs。配列は参照渡しできないため、これは間違っていませんか?
VIII.6:値によって配列を関数に渡すにはどうすればよいですか?
回答:末尾に角括弧(_
[
_および_]
_)を付けた配列名を呼び出し先関数で宣言することにより、値によって関数に配列を渡すことができます。関数を呼び出すとき、呼び出された関数に配列のアドレス(つまり、配列の名前)を渡すだけです。たとえば、次のプログラムは、配列_x[]
_を値によってbyval_func()
という名前の関数に渡します。_
int[]
_パラメーターは、byval_func()
関数が1つの引数(整数の配列)を取ることをコンパイラーに伝えます。byval_func()
関数が呼び出されると、配列のアドレスをbyval_func()
に渡します。_byval_func(x);
_配列は値で渡されるため、配列の正確なコピーが作成され、スタックに配置されます。呼び出された関数は、この配列のコピーを受け取り、印刷できます。
byval_func()
に渡される配列は元の配列のコピーであるため、byval_func()
関数内の配列を変更しても元の配列には影響しません。
配列は値で渡されるため、配列の正確なコピーが作成され、スタックに配置されます。
これは正しくありません:配列自体はコピーされません、そのアドレスへのポインタのコピーのみが呼び出し先に渡されます(スタックに配置されます) 。 (パラメーターをint[]
として宣言するかint*
として宣言するかにかかわらず、それは decays into pointer 。)これにより、呼び出された関数内から配列の内容を変更できます。したがって、これ
Byval_func()に渡される配列は元の配列のコピーであるため、byval_func()関数内で配列を変更しても元の配列には影響しません。
は明らかに間違っています(以下のコメントについて@Jonathan Lefflerに感謝します)。ただし、関数内でポインターを再割り当てしても、関数外の元の配列へのポインターは変更されません。
その本を燃やす。実際のC FAQ初心者プログラマーによって書かれたものではない場合は、これを使用してください: http://c-faq.com/aryptr/index.html 。
構文的には、厳密に言えばcannotはCの値で配列を渡します。
void func (int* x); /* this is a pointer */
void func (int x[]); /* this is a pointer */
void func (int x[10]); /* this is a pointer */
ただし、、レコードにはCの値で配列を渡すことができるCの汚いトリックがあります。これを自宅で試さないでください!このトリックにもかかわらず、値で配列を渡す理由はまだないためです。
typedef struct
{
int my_array[10];
} Array_by_val;
void func (Array_by_val x);
CおよびC++では、値としてメモリの完全なブロックをパラメーターとして関数に渡すことはできませんが、そのアドレスを渡すことは許可されています。実際には、これはほぼ同じ効果があり、はるかに高速で効率的な操作です。
安全のために、配列サイズを渡すか、ポインタの前にconst修飾子を配置して、呼び出し先がそれを変更しないようにすることができます。