sizeof(arr) / sizeof(arr[0]) 是如何工作的?

How do sizeof(arr) / sizeof(arr[0]) work?

在 for 循环中查找数组的大小时,我看到有人写

int arr[10];
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){}

sizeof(arr) / sizeof(arr[0])数组的长度是多少?它在技术上是如何工作的?

如果你有一个 array 那么 sizeof(array) returns 数组占用的字节数。由于每个元素可以占用 space 的 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

LIVE EXAMPLE

请注意,如果您将数组传递给函数,上述方法将不起作用,因为数组会衰减为指针并且 sizeof(array) returns 指针的大小。

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()

LIVE EXAMPLE #2

只有arr没有衰减成指针类型才有效,即是数组类型,不是指针类型

sizeof(arr)是数组占用的总大小

sizeof(arr[0]) 是数组中第一个元素的大小。 (请注意,零长度数组在 C++ 中是不允许的,因此如果数组本身存在,则此元素始终存在)。

由于所有元素的大小都相同,因此元素的数量为 sizeof(arr) / sizeof(arr[0])

处理数组时(some_type name[some_size]) sizeof(name)是数组占多少字节。将数组的总大小除以一个元素的大小 (sizeof(name[0])) 得到数组中有多少个元素。

如 C++ 标准 (5.3.3 Sizeof) 中所述

1 The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 5), or a parenthesized type-id.

在这个表达式中

sizeof(arr) / sizeof(arr[0])

使用了两个带有 sizeof 运算符的子表达式。

这个子表达式

sizeof(arr)

产生数组 arr 占用的字节数(我假设 arr 是一个数组)。

例如,如果您声明了一个数组

int arr[10];

然后编译器必须预留内存来容纳 10 个 int 类型的元素。例如,如果 sizeof( int ) 等于 4,那么编译器将保留 10 * 4 = 40 字节的内存。

子表达式

sizeof(arr[0])

给出数组中一个元素占用的字节数。您可以使用任何索引,例如

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 个字节,具体取决于使用的环境。而且你不会得到元素的数量。你会得到一些奇怪的值。

c++使用extent的方式,可以得到数组第N维的元素个数。 详情见 http://en.cppreference.com/w/cpp/types/extent

int values[] = { 1 };

std::extent<decltype(values)>::value == 1

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, 就是数组的长度。

让我们举个例子,比如 arr[]={1,2,4,3,5}

那么数组的大小将为 5,arr[0] 的大小将为“1”,因为它包含一个元素。基本上它是一个子数组,从上面的问题来看,它将是 5/1 它将自动 returns 数组的大小 =5.

区别在于 int arr[5] = {1,2,3,4,5}; 这里 arr 是指向数组 的指针, &arr[0] 是 Integer

类型的指针