web-dev-qa-db-ja.com

関数に特定のサイズの配列パラメーターがある場合、なぜポインターに置き換えられるのですか?

次のプログラムを考えると、

#include <iostream>

using namespace std;

void foo( char a[100] )
{
    cout << "foo() " << sizeof( a ) << endl;
}

int main()
{
    char bar[100] = { 0 };
    cout << "main() " << sizeof( bar ) << endl;
    foo( bar );
    return 0;
}

出力

main() 100
foo() 4
  1. 配列が最初の要素へのポインタとして渡されるのはなぜですか?
  2. Cの遺産ですか?
  3. 標準は何と言っていますか?
  4. C++の厳密な型安全性が低下するのはなぜですか?
65
CsTamas

はい、Cから継承されます。関数:

void foo ( char a[100] );

パラメーターがポインターになるように調整されるため、次のようになります。

void foo ( char * a );

配列タイプを保持したい場合は、配列への参照を渡す必要があります。

void foo ( char (&a)[100] );

C++ '03 8.3.5/3:

...関数のタイプは、次のルールを使用して決定されます。各パラメーターのタイプは、独自のdecl-specifier-seqおよび宣言子から決定されます。各パラメーターのタイプを決定した後、「Tの配列」または「Tを返す関数」タイプのパラメーターは、それぞれ「Tへのポインター」または「Tを返す関数へのポインター」に調整されます。

構文を説明するには:

グーグルで「左右」ルールを確認してください。私はそれの説明を見つけました ここ

この例には、およそ次のように適用されます。

void foo (char (&a)[100]);

識別子「a」から開始

「a」は

右に移動-)そのため、(。左に移動すると、&

「a」は参照です

後に &開口部に到達(そのため、再び逆向きになり、正しく見えるようにします。 [100]

'a'は100の配列への参照です

そして、charに達するまで再び方向を逆にします。

'a'は100文字の配列への参照です

77
Richard Corden

はい。 CおよびC++では、配列を関数に渡すことはできません。仕方ないよ。

とにかくプレーン配列をしているのはなぜですか? boost/std::tr1::array/std::arrayまたはstd::vectorを見ましたか?

ただし、任意の長さの配列への参照を関数templateに渡すことができます。私の頭の上から:

template< std::size_t N >
void f(char (&arr)[N])
{
  std::cout << sizeof(arr) << '\n';
}
13
sbi

C/C++の用語には、静的配列と関数ポインターに使用される素晴らしいWordがあります-decay。次のコードを検討してください。

int intArray[] = {1, 3, 5, 7, 11}; // static array of 5 ints
//...
void f(int a[]) {
  // ...
}
// ...
f(intArray); // only pointer to the first array element is passed
int length = sizeof intArray/sizeof(int); // calculate intArray elements quantity (equals 5)
int ptrToIntSize = sizeof(*intArray); // calculate int * size on your system
0
DaddyM