126

Cの2つの関数の違いは何ですか?

void f1(double a[]) {
   //...
}

void f2(double *a) {
   //...
}

かなり長い配列で関数を呼び出す場合、これら2つの関数の動作は異なりますか?スタック上でより多くのスペースを使用しますか?

4

3 に答える 3

127

まず、いくつかの標準

6.7.5.3関数宣言子(プロトタイプを含む)
... 7''
の配列''としてのパラメーターの宣言は、''への修飾ポインター''に調整されるものとします 。ここで、型修飾子(存在する場合)は指定されたものです。配列型派生のおよび内。キーワードが配列タイプの派生のおよび内にも表示される場合、関数の呼び出しごとに、対応する実際の引数の値は、少なくともサイズで指定された数の要素を持つ配列の最初の要素へのアクセスを提供するものとします。表現。 []static[]

したがって、要するに、として宣言された、T a[]または宣言されたかのようT a[N]に扱われるT *a関数パラメータはすべてです。

では、なぜ配列パラメーターはポインターとして宣言されているかのように扱われるのでしょうか。理由は次のとおりです。

6.3.2.1左辺値、配列、および関数指定子
... 3演算子または単項演算子
のオペランドである場合、または配列を初期化するために使用される文字列リテラルである場合を除き、「型の配列」の式'は、配列オブジェクトの初期要素を指し、左辺値ではない' '型''ポインタから型''の式に変換されます。配列オブジェクトにレジスタストレージクラスがある場合、動作は未定義です。 sizeof&

次のコードが与えられます:

int main(void)
{
  int arr[10];
  foo(arr);
  ...
}

の呼び出しでfooは、配列式arrはまたはのいずれのオペランドでもないsizeofため、6.2.3.1 / 3に従って&、その型は「の10要素配列int」から「ポインタ」に暗黙的に変換されintます。したがって、foo配列値ではなく、ポインタ値を受け取ります。

6.7.5.3/7のため、次のように書くことができfooます

void foo(int a[]) // or int a[10]
{
  ...
}

しかし、それは次のように解釈されます

void foo(int *a)
{
  ...
}

したがって、2つの形式は同じです。

6.7.5.3/7の最後の文は、C99で導入されました。これは、基本的に、次のようなパラメーター宣言がある場合を意味します。

void foo(int a[static 10])
{
  ...
}

に対応する実際のパラメータは、少なくとも10個の要素aを持つ配列である必要があります。

于 2011-04-06T22:29:20.683 に答える
32

違いは純粋に構文的なものです。Cでは、配列表記が関数パラメーターに使用されると、それは自動的にポインター宣言に変換されます。

于 2011-04-06T21:42:42.113 に答える
0

いいえ、違いはありません。テストするために、このCコードをDev C ++(mingw)コンパイラで記述しました。

#include <stdio.h>

void function(int* array) {
     int a =5;
}

void main() {  
     int array[]={2,4};
     function(array);
     getch();
}

IDAのバイナリファイルの両方の呼び出しバージョンの.exeでメイン関数を逆アセンブルすると、次のようなまったく同じアセンブリコードが得られます。

push    ebp
mov     ebp, esp
sub     esp, 18h
and     esp, 0FFFFFFF0h
mov     eax, 0
add     eax, 0Fh
add     eax, 0Fh
shr     eax, 4
shl     eax, 4
mov     [ebp+var_C], eax
mov     eax, [ebp+var_C]
call    sub_401730
call    sub_4013D0
mov     [ebp+var_8], 2
mov     [ebp+var_4], 4
lea     eax, [ebp+var_8]
mov     [esp+18h+var_18], eax
call    sub_401290
call    _getch
leave
retn

したがって、この呼び出しの2つのバージョンに違いはありません。少なくとも、コンパイラーはそれらを等しく脅かします。

于 2011-04-06T21:54:02.307 に答える