web-dev-qa-db-fra.com

Comment fonctionnent sizeof (arr)/sizeof (arr [0])?

Lors de la recherche de la taille d'un tableau dans une boucle for, j'ai vu des gens écrire

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

Comment sizeof(arr) / sizeof(arr[0]) est-il la longueur du tableau? Comment ça marche techniquement?

17
Felix Willis

Si vous avez une array, alors sizeof(array) renvoie le nombre d'octets occupés par le tableau. Étant donné que chaque élément peut occuper plus d'un octet, vous devez diviser le résultat par la taille d'un élément (sizeof(array[0])). Cela vous donne le nombre d'éléments dans le tableau.

Exemple:

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

EXEMPLE EN DIRECT

Notez que si vous transmettez un tableau à une fonction, cela ne fonctionnera pas, car le tableau se décompose en un pointeur et sizeof(array) renvoie la taille du pointeur.

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

EXEMPLE DE LIVE N ° 2

27
rozina

Comme décrit dans la norme C++ (5.3.3 Sizeof)

1 L'opérateur sizeof donne le nombre d'octets de l'objet représentation de son opérande. L'opérande est soit une expression, qui est un opérande non évalué (clause 5) ou une parenthèse type-id.

Dans cette expression

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

on utilise deux sous-expressions avec l'opérateur sizeof.

Cette sous-expression

sizeof(arr)

donne le nombre d'octets occupés par le tableau arr (je suppose que arr est un tableau).

Par exemple, si vous avez déclaré un tableau comme

int arr[10];

alors le compilateur doit réserver de la mémoire pour contenir 10 éléments de type int. Si, par exemple, sizeof( int ) est égal à 4, le compilateur réservera 10 * 4 = 40 octets de mémoire.

Sous expression

sizeof(arr[0])

donne le nombre d'octets occupés par un élément du tableau. Vous pouvez utiliser n'importe quel index comme par exemple

sizeof(arr[1000])

parce que l'expression n'est pas évaluée. La taille en octets de l'objet (un élément du tableau) utilisé dans l'opérateur est importante.

Donc, si vous connaissez le nombre total d'octets réservés pour un tableau

sizeof(arr)

et savoir combien d'octets chaque élément du tableau occupe (tous les éléments d'un tableau ont la même taille), vous pouvez alors calculer le nombre d'éléments dans le tableau en utilisant la formule

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

Voici une relation simple. Si vous avez un tableau de N éléments de type T

T arr[N];

et vous connaissez la taille de la mémoire occupée par le tableau, alors vous pouvez calculer la taille de son élément en utilisant la formule

sizeof( arr ) / N == size of an element of the array. 

Et vice versa

Si vous connaissez la taille de la mémoire occupée par le tableau et la taille de son élément, vous pouvez calculer le nombre d'éléments dans le tableau.

sizeof( arr ) / sizeof( a[0] ) == N - number of elements in the array

La dernière expression que vous pouvez réécrire aussi de la manière suivante

sizeof( arr ) / sizeof( T ) == N - number of elements in the array

parce que les éléments du tableau ont le type T et que chaque élément du tableau occupe exactement le nombre d'octets requis pour allouer un objet de type T.

Tenez compte du fait que ce sont généralement les débutants qui font une telle erreur. Ils passent un tableau en tant qu'argument à une fonction. Par exemple, supposons que vous ayez une fonction

void f( int a[] )
{
   // ...
}

Et vous passez à la fonction votre tableau

int arr[10];
f(arr);

alors la fonction utilise le pointeur sur le premier élément du tableau. En fait, la fonction a une déclaration

void f( int *a )
{
   // ...
}

Donc, si vous écrivez par exemple dans la fonction

void f( int *a )
{
   size_t n = sizeof( a ) / sizeof( a[0] );
   // ...
}

alors comme a dans la fonction est un pointeur (ce n'est pas un tableau), alors vous obtiendrez quelque chose comme

void f( int *a )
{
   size_t n = sizeof( int * ) / sizeof( int );
   // ...
}

Généralement, la taille d'un pointeur est égale à 8 ou 4 octets, en fonction de l'environnement utilisé. Et vous n'obtiendrez pas le nombre d'éléments. Vous obtiendrez une valeur étrange.

4
Vlad from Moscow

Cela ne fonctionne que si arr n'a pas été décomposé en pointeur, c'est-à-dire qu'il s'agit d'un type de tableau, pas un type de pointeur.

sizeof(arr) est la taille totale occupée par le tableau.

sizeof(arr[0]) est la taille du premier élément du tableau. (Notez que les tableaux de longueur nulle ne sont pas autorisés en C++, donc cet élément existe toujours si le tableau lui-même existe).

Comme tous les éléments auront la même taille, le nombre d’éléments est sizeof(arr) / sizeof(arr[0]).

3
Bathsheba

int - est égal à 4 octets
sizeof(int) cela signifie: 1 * 4 = 4

int arr[10] - tient 10 int
sizeof(arr) cela signifie: 10 * 4 = 40, nous avons 10 int et chaque int a 4 octets , arr sans le [] cela signifie toute la arr.

sizeof(arr[0]) cela signifie: 1 * 4 = 4

sizeof(arr) / sizeof(arr[0]) = 10 * 4/1 * 4 = 10 , et c'est la longueur du tableau.

2
Wasif Anton

Lorsqu’il s’agit d’un tableau (some_type name[some_size]), sizeof(name) est le nombre d’octets qu’il occupe. En divisant la taille totale du tableau par la taille d'un élément (sizeof(name[0])), vous obtenez le nombre d'éléments contenus dans le tableau.

1
NathanOliver

c ++ manière d’utiliser l’extension, ce qui vous permet d’obtenir un certain nombre d’éléments dans la Nième dimension du tableau . voir http://fr.cppreference.com/w/cpp/types/extent pour plus de détails.

int values[] = { 1 };

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