19

たとえば、配列の長さを取得したいint array[] = {1, 2, 3, 4}。私sizeofはそれをしていました。

int length(int array[])
{
     return sizeof(array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

では、なぜsizeof(array)in 関数lengthは のポインター サイズを返すのarrayでしょうか? しかし、 functionmainでは機能します。

lengthまた、配列の長さを取得するには、関数をどのように変更すればよいですか?

4

8 に答える 8

26

C の特別な規則では、関数パラメーターの場合、配列型はポインター型に調整されます。つまり、次のことを意味します。

int length(int array[]);

と同等です

int length(int *array);

したがってsizeof、配列を計算すると、実際にはポインターのサイズが計算されます。

(C99、6.7.5.3p7) 「「型の配列」としてのパラメーターの宣言は、「型への修飾ポインター」に調整されます。型修飾子 (存在する場合) は、配列の [ および ] 内で指定されたものです。型派生。」

于 2012-07-23T23:51:46.777 に答える
6

配列を関数に渡すと、配列はポインターに崩壊します。

于 2012-07-23T23:49:17.590 に答える
5

他の回答者が指摘したように、配列を取るように宣言された関数は、ポインターを取った場合と同じようにコンパイルされます。

length メソッドを実行する最も一般的な方法は #define を使用する方法ですが、テンプレートを使用してトリックを行うと、関数を機能させることができます。

template <size_t _Size> inline int length(int(& array)[_Size])
{
    //return sizeof(array) / sizeof(int);
    return _Size;
};

int array[] = {1, 2, 3, 4};
printf("%d\n", length(array)); // print 4

長さ 4 の配列を使用すると、これは長さ 4 の配列を受け取り、静的な 4 を返すメソッドとしてコンパイルされます。これには、配列ではないものを渡そうとすると、コンパイラが与えるという利点もあります。 #define メソッドではエラーになりません。

int* foo = array;
printf("%d\n", length(foo)); 
    // error C2784: 'int length(int (&)[_Size])' : could not deduce template
    //     argument for 'int (&)[_Size]' from 'int *'
    // test.cpp(56) : see declaration of 'length'
于 2012-07-24T01:31:29.807 に答える
3

メインプログラムでは、コンパイラは配列の長さを認識しています。サブルーチンでは、そうではありません。特に、サブルーチンでは、 type のパラメーターは typeint[]のパラメーターと同じですint *。一方、メインプログラムでは、arraytype がありint[4]ます。array(これは、別の値をin sideに代入することでテストできますmain。コンパイラは文句を言います。)

于 2012-07-23T23:47:25.647 に答える
2

C は、配列のサイズに関するランタイム メタデータを変数と共に保存しません。それを自分でどこかに保存する必要があります。

メソッドの長さのコンテキストにおけるint[]型の変数は、メモリ ブロックへの単なるポインタです。そのため、サイズはシステム上の他のポインターのサイズと同じです。

sizeofがコンパイル時に (メイン関数のように) 配列にアクセスできる場合、代わりに配列が占めるバイト数を返します。

于 2012-07-23T23:47:01.980 に答える
2

length渡された配列の実際のサイズを知りたい場合は、誰もが言うように、その情報を渡す必要があります。ただし、情報が組み込まれた配列への参照を受け取ることも可能です。

int length(int n, int (* array)[n])
{
     return sizeof(*array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(4, &array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

そもそもサイズがすでに提供されているため、実際に何が役立つかはわかりません。しかしsizeof、この場合、オペレーターが意図したとおりに機能することがわかります。

于 2012-07-23T23:57:24.140 に答える
0

長さの内側の可変配列は外側のものと同じではないためです。メイン関数で sizeof(array) / sizeof(int) を保持する必要があります。

于 2012-07-23T23:47:31.707 に答える
0

length配列の長さを取得できるようにコードを変更するには、コードをマクロに変換します。

#define length(x) (sizeof(x)/sizeof(*x))

コード サンプルでは、​​これは期待どおりに動作します。

これは、静的に割り当てられた配列でのみ機能し、元の配列を使用して呼び出された場合にのみ機能することに注意してください (配列へのポインターを使用する場合は機能しません)。これは、sizeof(x)wherexを配列へのポインターと記述すると、コンパイラーが文字どおりに解釈するためです。xを評価する前に、それが指す配列にマッピングする方法はありませんsizeof

于 2012-07-23T23:51:41.327 に答える