web-dev-qa-db-fra.com

Nombre d'éléments d'un tableau en C ++

Disons que j'ai un tableau arr. Quand les éléments suivants ne donneraient-ils pas le nombre d'éléments du tableau: sizeof(arr) / sizeof(arr[0])?

Je ne peux penser qu'à un seul cas: le tableau contient des éléments qui sont de différents types dérivés du type du tableau.

Ai-je raison et y a-t-il (je suis presque positif doit être) d'autres cas de ce genre?

Désolé pour la question banale, je suis un Java dev et je suis plutôt nouveau en C++.

Merci!

21
Albus Dumbledore

Disons que j'ai un tableau arr. Quand les éléments suivants ne donneraient-ils pas le nombre d'éléments du tableau: sizeof (arr)/sizeof (arr [0])?

J'ai souvent vu de nouveaux programmeurs faire ceci:

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

Sample arr[10];
f(arr);

Les nouveaux programmeurs pensent donc que la valeur de count sera de 10. Mais c'est faux.

Même cela est faux:

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

C'est parce qu'une fois que vous passez un tableau à l'une de ces fonctions, il devient pointeur type, et donc sizeof(arr) donnerait la taille de pointeur, pas tableau!


ÉDITER:

Ce qui suit est une manière élégante de passer un tableau à une fonction, sans le laisser se désintégrer en type de pointeur:

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

Les tableaux en C++ sont très différents de ceux de Java en ce qu'ils sont complètement non gérés. Le compilateur ou le run-time n'ont aucune idée de la taille du tableau.

Les informations ne sont connues au moment de la compilation que si la taille est définie dans la déclaration:

char array[256];

Dans ce cas, sizeof (array) vous donne la bonne taille.

Cependant, si vous utilisez un pointeur comme tableau, le "tableau" ne sera qu'un pointeur et sizeof ne vous donnera aucune information sur la taille réelle du tableau.

STL propose de nombreux modèles qui vous permettent d'avoir des tableaux, certains avec des informations sur la taille, certains avec des tailles variables et la plupart avec de bons accesseurs et une vérification des limites.

9
EboMike

Il n'y a aucun cas où, étant donné un tableau arr, la valeur de sizeof(arr) / sizeof(arr[0]) n'est pas le nombre d'éléments, par la définition de array et sizeof.

En fait, il est même directement mentionné (§5.3.3/2):

.... Lorsqu'il est appliqué à un tableau, le résultat est le nombre total d'octets dans le tableau. Cela implique que la taille d'un tableau d'éléments n est n fois la taille d'un élément.

Je souligne. Divisez par la taille d'un élément, sizeof(arr[0]), pour obtenir n .

7
GManNickG

Non, cela produirait toujours la bonne valeur car vous devez définir le tableau comme étant tous les éléments d'un seul type ou des pointeurs vers un type. Dans les deux cas, la taille du tableau est connue au moment de la compilation, donc sizeof (arr)/sizeof (arr [0]) renvoie toujours le nombre d'éléments.

Voici un exemple de la façon de l'utiliser correctement:

int nonDynamicArray[ 4 ];

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

J'irai plus loin ici pour montrer quand pour l'utiliser correctement. Vous ne l'utiliserez pas très souvent. Il est principalement utile lorsque vous souhaitez définir un tableau spécifiquement afin de pouvoir y ajouter des éléments sans changer beaucoup de code plus tard. C'est une construction qui est principalement utile pour maintenance. L'exemple canonique (quand j'y pense quand même ;-) construit une table de commandes pour un programme auquel vous avez l'intention d'ajouter plus commandes plus tard. Dans cet exemple, pour maintenir/améliorer votre programme, il vous suffit d'ajouter une autre commande au tableau, puis d'ajouter le gestionnaire de commandes:

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

Disons que j'ai un tableau arr. Quand les éléments suivants ne donneraient-ils pas le nombre d'éléments du tableau: sizeof(arr) / sizeof(arr[0])?

Dans les contextes où arr n'est pas réellement le tableau (mais plutôt un pointeur vers l'élément initial). D'autres réponses expliquent comment cela se produit.

Je ne peux penser qu'à un seul cas: le tableau contient des éléments qui sont de différents types dérivés du type du tableau.

Cela ne peut pas se produire (pour, fondamentalement, la même raison que Java ne fonctionnent pas bien avec les génériques). Le tableau est typé statiquement; il réserve des "emplacements" de mémoire qui sont dimensionnés pour un type spécifique (le type de base).

Désolé pour la question banale, je suis un Java dev et je suis plutôt nouveau en C++.

Les tableaux C++ ne sont pas des objets de première classe. Vous pouvez utiliser boost :: array pour les faire se comporter davantage comme Java, mais gardez à l'esprit que vous aurez toujours la sémantique de valeur plutôt que la sémantique de référence, comme avec tout le reste. (En particulier , cela signifie que vous ne pouvez pas vraiment déclarer une variable de type analogue à Foo[] en Java, ni remplacer un tableau par un autre de taille différente; la taille du tableau fait partie du type.) Utilisez la fonction .size() avec cette classe où vous utiliseriez .length en Java (il fournit également des itérateurs qui fournissent l'interface habituelle pour les itérateurs C++).

1
Karl Knechtel

Utilisez la macro Microsoft "_countof (array)". Ce lien vers le Microsoft Developer Network l'explique et offre un exemple qui montre la différence entre "sizeof (array)" et la macro "_countof (array)".

Microsoft et la macro "_countof (array)"

1
jamesc1101

Tout d'abord, vous pouvez contourner ce problème en utilisant std::vector au lieu d'un tableau. Deuxièmement, si vous placez des objets d'une classe dérivée dans un tableau d'une super classe, vous ferez l'expérience du découpage, mais la bonne nouvelle est que votre formule fonctionnera. Les collections polymorphes en C++ sont obtenues à l'aide de pointeurs. Il y a trois options principales ici:

1
Björn Pollex

_countof (my_array) dans MSVC

Je ne peux penser qu'à un seul cas: le tableau contient des éléments qui sont de différents types dérivés du type du tableau.

Les éléments d'un tableau en C++ sont des objets, pas des pointeurs, vous ne pouvez donc pas avoir d'objet de type dérivé comme élément.

Et comme mentionné ci-dessus, sizeof (my_array) (comme _countof () également) fonctionnera uniquement dans le cadre de la définition du tableau.

0
Mindaugas P.