Forループで配列のサイズを探すとき、私は人々が書くのを見ました
_int arr[10];
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){}
_
sizeof(arr) / sizeof(arr[0])
は配列の長さですか?技術的にはどのように機能しますか?
array
がある場合、sizeof(array)
は配列が占有するバイト数を返します。各要素は1バイト以上のスペースを取る可能性があるため、結果を1つの要素のサイズ(sizeof(array[0])
)で除算する必要があります。これにより、配列内の要素数がわかります。
例:
_std::uint32_t array[10];
auto sizeOfInt = sizeof(std::uint32_t); // 4
auto numOfBytes = sizeof(array); // 10*sizeOfInt = 40
auto sizeOfElement = sizeof(array[0]); // sizeOfInt = 4
auto numOfElements = sizeof(array) / sizeof(array[0]); // numOfBytes / sizeOfElement = 40 / 4 = 10
_
関数に配列を渡すと、配列がポインターに減衰し、sizeof(array)
がポインターのサイズを返すため、上記は機能しません。
_std::size_t function(std::uint32_t a[]) // same for void function(std::uint32_t a[10])
{
return sizeof(a); // sizeof(std::uint32_t*)!
}
std::uint32_t array[10];
auto sizeOfArray = function(array); // array decays to a pointer inside function()
_
C++標準(5.3.3 Sizeof)に記載されているとおり
1 sizeof演算子は、そのオペランドのオブジェクト表現のバイト数を生成します。オペランドは、評価されていないオペランドである式(5項)、または括弧で囲まれたtype-idのいずれかです。
この表現では
_sizeof(arr) / sizeof(arr[0])
_
sizeof演算子で2つの部分式が使用されます。
この部分式
_sizeof(arr)
_
配列arr
(arr
は配列であると仮定します)が占有するバイト数を返します。
たとえば、次のような配列を宣言した場合
_int arr[10];
_
次に、コンパイラは、int型の10個の要素を保持するメモリを予約する必要があります。たとえば、sizeof( int )
が4の場合、コンパイラは10 * 4 = 40バイトのメモリを予約します。
部分式
_sizeof(arr[0])
_
配列内の1つの要素が占めるバイト数を示します。たとえば、任意のインデックスを使用できます
_sizeof(arr[1000])
_
式が評価されていないためです。演算子内で使用されるオブジェクト(配列の要素)のバイト単位のサイズのみが重要です。
したがって、配列用に予約された合計バイト数がわかっている場合
_sizeof(arr)
_
配列の各要素が占めるバイト数(配列のすべての要素が同じサイズを持っている)がわかっている場合は、式を使用して配列内の要素の数を計算できます
_sizeof(arr) / sizeof(arr[0])
_
以下に簡単な関係を示します。タイプTのN個の要素の配列がある場合
_T arr[N];
_
配列が占有するメモリのサイズがわかっている場合は、式を使用して要素のサイズを計算できます
_sizeof( arr ) / N == size of an element of the array.
_
そしてその逆
配列が占めるメモリのサイズとその要素のサイズがわかっている場合、配列内の要素の数を計算できます
_sizeof( arr ) / sizeof( a[0] ) == N - number of elements in the array
_
最後の式は次の方法でも書き直すことができます
_sizeof( arr ) / sizeof( T ) == N - number of elements in the array
_
配列の要素はT型であり、配列の各要素は、T型のオブジェクトを割り当てるのに必要なバイト数を正確に占有するためです。
通常、初心者がそのようなエラーを犯していることを考慮してください。関数への引数として配列を渡します。たとえば、関数があると仮定しましょう
_void f( int a[] )
{
// ...
}
_
そして、配列に関数を渡します
_int arr[10];
f(arr);
_
次に、関数は配列の最初の要素へのポインターを使用します。実際、関数には宣言があります
_void f( int *a )
{
// ...
}
_
したがって、たとえば関数内で書く場合
_void f( int *a )
{
size_t n = sizeof( a ) / sizeof( a[0] );
// ...
}
_
関数内のa
はポインタであるため(配列ではありません)、次のようなものが得られます
_void f( int *a )
{
size_t n = sizeof( int * ) / sizeof( int );
// ...
}
_
通常、使用される環境に応じて、8または4バイトのいずれかに等しいポインターのサイズ。そして、あなたは要素の数を取得しません。奇妙な値を取得します。
arr
がポインターに減衰されていない場合にのみ機能します。つまり、配列型、notポインター型です。
sizeof(arr)
は、配列が占める合計サイズです。
sizeof(arr[0])
は、配列の最初の要素のサイズです。 (C++では長さゼロの配列は許可されないため、配列自体が存在する場合、この要素は常に存在することに注意してください)。
すべての要素は同じサイズになるため、要素の数はsizeof(arr) / sizeof(arr[0])
です。
int
-4バイトに等しいsizeof(int)
意味:1 * 4 = 4
_int arr[10]
_-10を保持していますint
sizeof(arr)
意味:10 * 4 = 40、10個のint
を取得し、すべてのint
が4バイトを取得、_arr
なしで_[]
_それはすべてのarr
を意味します。
sizeof(arr[0])
意味:1 * 4 = 4
sizeof(arr) / sizeof(arr[0])
= 10 * 4/1 * 4 =10。これは配列の長さです。
配列を扱うとき(_some_type name[some_size]
_)sizeof(name)
は配列が占めるバイト数です。配列の合計サイズを1つの要素のサイズ(sizeof(name[0])
)で割ると、配列に含まれる要素の数がわかります。
エクステントを使用するc ++の方法。これにより、uは配列のN次元の要素の数を取得できます。詳細については、 http://en.cppreference.com/w/cpp/types/extent を参照してください
int values[] = { 1 };
std::extent<decltype(values)>::value == 1