web-dev-qa-db-ja.com

C ++の配列の要素数

配列arrがあるとします。次の場合、配列の要素数が得られない場合:sizeof(arr) / sizeof(arr[0])

私はたった1つの場合にしかできません。配列には、配列の型の異なる派生型の要素が含まれています。

私は正しいですか、そこにいます(私はそこにほとんど肯定的です必ずそうです)他のそのような場合は?

些細な質問で申し訳ありませんが、私はJava devであり、C++の初心者です。

ありがとう!

21

配列arrがあるとします。以下は、配列の要素数を与えない場合:sizeof(arr)/ sizeof(arr [0])?

新しいプログラマーがこれをしているのをよく見かけます。

_void f(Sample *arr)
{
   int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}

Sample arr[10];
f(arr);
_

新しいプログラマーは、countの値は10になると考えていますが、それは間違っています。

これでも間違っています:

_void g(Sample arr[]) //even more deceptive form!
{
   int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10  
}
_

配列をこれらの関数のいずれかに渡すと、配列はpointer typeになるため、sizeof(arr)はサイズをpointerではなく、アレイ!


編集:

以下は、配列をポインター型に減衰させずに、配列を関数に渡すことができるエレガントな方法です。

_template<size_t N>
void h(Sample (&arr)[N])
{
    size_t count = N; //N is 10, so would be count!
    //you can even do this now:
    //size_t count = sizeof(arr)/sizeof(arr[0]);  it'll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!
_
30
Nawaz

C++の配列は、完全に管理されていないという点でJavaの配列とは非常に異なります。コンパイラーまたはランタイムは、配列のサイズがまったくわからない。

情報は、サイズが宣言で定義されている場合にのみコンパイル時に認識されます。

char array[256];

この場合、sizeof(array)は適切なサイズを提供します。

ただし、ポインターを配列として使用する場合、「配列」は単なるポインターになり、sizeofは配列の実際のサイズに関する情報を提供しません。

STLには多くのテンプレートが用意されており、その中にはサイズ情報を持つもの、可変サイズを持つもの、ほとんどが優れたアクセサーと境界チェックを持つ配列があります。

9
EboMike

配列arrが与えられた場合、配列とsizeofの定義により、sizeof(arr) / sizeof(arr[0])の値が要素の数ではない場合はありません。

実際、直接言及されています(§5.3.3/ 2):

....配列に適用されると、結果は配列内の合計バイト数になります。 これはn要素の配列のサイズがn倍の要素のサイズであることを意味します =

強調鉱山。要素のサイズsizeof(arr[0])で除算して、nを取得します。

7
GManNickG

いいえ、配列は単一の型のすべての要素または型へのポインターのいずれかとして定義する必要があるため、それでも正しい値が生成されます。いずれの場合も、コンパイル時に配列サイズがわかるため、sizeof(arr)/ sizeof(arr [0])は常に要素数を返します。

これを正しく使用する方法の例を次に示します。

int nonDynamicArray[ 4 ];

#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )

これを適切に使用するためにwhenを表示するために、ここにさらに進んでいきます。あまり頻繁には使用しません。これは主に、後で多くのコードを変更せずに要素を追加できるように配列を明確に定義する場合に役立ちます。これは、主にmaintenanceに役立つ構造です。正規の例(とにかく考えてみると;-)は、プログラムにmoreコマンドを後で追加する予定のコマンドのテーブルを作成しています。この例では、プログラムを保守/改善するために必要なことは、別のコマンドを配列に追加してから、コマンドハンドラーを追加することだけです。

char        *commands[] = {  // <--- note intentional lack of explicit array size
    "open",
    "close",
    "abort",
    "crash"
};

#define kCommandsCount  ( sizeof(commands) / sizeof(commands[ 0 ]) )

void processCommand( char *command ) {
    int i;

    for ( i = 0; i < kCommandsCount; ++i ) {
        // if command == commands[ i ] do something (be sure to compare full string)
    }
}
4
par

配列arrがあるとします。以下は、配列の要素数を与えない場合:sizeof(arr) / sizeof(arr[0])

arrが実際には配列ではないコンテキスト(ただし、代わりに初期要素へのポインター)。他の答えは、これがどのように起こるかを説明します。

私はたった1つの場合にしかできません。配列には、配列の型の異なる派生型の要素が含まれています。

これは起こりえません(基本的に、Java配列がジェネリックとうまく動作しない同じ理由で)。配列は静的に型付けされます;それは、特定のタイプ(基本タイプ)。

些細な質問で申し訳ありませんが、私はJava devであり、C++の初心者です。

C++配列はファーストクラスのオブジェクトではありません。 boost :: arrayを使用して、それらをJava配列のように動作させることができますが、他のすべての場合と同様に、参照セマンティクスではなく値セマンティクスを引き続き使用できることに注意してください。 、つまり、JavaでFoo[]に類似した型の変数を実際に宣言することも、配列を別のサイズの別の配列で置き換えることもできません。配列サイズは型の一部です。)このクラスで.size()を使用しますJavaで.lengthを使用する場所(C++イテレータの通常のインターフェイスを提供するイテレータも提供します)。

1
Karl Knechtel

Microsoftの「_countof(array)」マクロを使用します。 Microsoft Developer Networkへのこのリンクはそれを説明し、「sizeof(array)」と「_countof(array)」マクロの違いを示す例を提供します。

Microsoftおよび「_c​​ountof(array)」マクロ

1
jamesc1101

まず、配列の代わりに std::vector を使用して、この問題を回避できます。第二に、派生クラスのオブジェクトをスーパークラスの配列に入れると、スライスが発生しますが、良いことに、式は機能します。 C++の多態的なコレクションは、ポインターを使用して実現されます。ここには3つの主要なオプションがあります。

1
Björn Pollex

MSVCの_countof(my_array)

私はたった1つの場合にしかできません。配列には、配列の型の異なる派生型の要素が含まれています。

C++の配列の要素はオブジェクトであり、ポインターではないため、派生型オブジェクトを要素として持つことはできません。

また、上記のように、sizeof(my_array)(_countof()も同様)は配列定義の範囲内でのみ機能します。

0
Mindaugas P.