Comment puis-je déterminer la taille de mon tableau en C?

Comment puis-je déterminer la taille de mon tableau en C?

C'est-à-dire le nombre d'éléments que le tableau peut contenir?

742
demandé sur Peter Mortensen 2008-09-01 10:49:22

21 réponses

Résumé:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

Pour déterminer la taille de votre tableau en octets, vous pouvez utiliser le sizeof opérateur:

int a[17];
size_t n = sizeof(a);

Sur mon ordinateur, les ints ont 4 octets de long, donc n est 68.

Pour déterminer le nombre d'éléments dans le tableau, nous pouvons diviser la taille totale de la matrice par la taille de l'élément de tableau. Vous pouvez le faire avec le type, comme ceci:

int a[17];
size_t n = sizeof(a) / sizeof(int);

Et obtenir la bonne réponse (68 / 4 = 17), mais si le type de a changé vous auriez un bug méchant si tu as oublié de changer le sizeof(int) aussi.

Donc le diviseur préféré est sizeof(a[0]), La Taille du zeroeth élément du tableau.

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

Un Autre avantage est que vous pouvez maintenant facilement paramétrer le nom du tableau dans une macro et obtient:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);
940
répondu Mark Harrison 2018-09-09 00:31:17

La voie sizeof est la bonne voie iff vous avez affaire à des tableaux non reçus en tant que paramètres. Un tableau envoyé en tant que paramètre à une fonction est traité comme un pointeur, donc sizeof retournera la taille du pointeur, au lieu du tableau.

Ainsi, inside functions cette méthode ne fonctionne pas. Au lieu de cela, passez toujours un paramètre supplémentaire size_t size indiquant le nombre d'éléments dans le tableau.

Essai:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

Sortie (dans un Linux 64 bits OS):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

Sortie (dans un système d'exploitation Windows 32 bits):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
640
répondu Elideb 2015-06-25 22:00:46

Il est à noter que sizeof n'aide pas lorsqu'il s'agit d'une valeur de tableau qui s'est décomposée en un pointeur: même si elle pointe vers le début d'un tableau, au compilateur, elle est identique à un pointeur vers un seul élément de ce tableau. Un pointeur ne "se souvient" de rien d'autre sur le tableau qui a été utilisé pour l'initialiser.

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
106
répondu Magnus Hoff 2014-10-06 06:44:37

Le sizeof "trick" est la meilleure façon que je connaisse, avec un petit mais (pour moi, c'est une bête noire majeure) changement important dans l'utilisation de la parenthèse.

Comme L'indique clairement L'entrée Wikipedia, C sizeof n'est pas une fonction; c'est un opérateur . Ainsi, il ne nécessite pas de parenthèse autour de son argument, sauf si l'argument est un nom de type. Ceci est facile à retenir, car il fait ressembler l'argument à une expression cast, qui utilise également des parenthèses.

Donc: si vous avez le suivant:

int myArray[10];

, Vous pouvez trouver le nombre d'éléments avec ce code:

size_t n = sizeof myArray / sizeof *myArray;

Cela, pour moi, se lit beaucoup plus facilement que l'alternative avec parenthèse. J'ai également en faveur de l'utilisation de l'astérisque dans la partie droite de la division, car il est plus concis que l'indexation.

Bien sûr, tout cela est aussi à la compilation, donc il n'y a pas besoin de s'inquiéter de la division affectant les performances du programme. Utilisez donc ce formulaire partout où vous le pouvez.

Il est toujours préférable d'utiliser sizeof sur un objet réel lorsque vous en avez un, plutôt que sur un type, depuis, vous n'avez pas besoin de vous soucier de faire une erreur et en précisant le type incorrect.

Par exemple, disons que vous avez une fonction qui génère des données sous forme de flux d'octets, par exemple sur un réseau. Nous allons appeler la fonction send(), et faire prendre comme argument un pointeur vers l'objet à envoyer, et le nombre d'octets dans l'objet. Ainsi, le prototype devient:

void send(const void *object, size_t size);

Et puis vous devez envoyer un entier, donc vous le coder comme ceci:

int foo = 4711;
send(&foo, sizeof (int));

Maintenant, vous avez introduit une façon subtile de vous tirer dans le pied, en spécifiant le type de foo à deux endroits. Si l'un change mais que l'autre ne le fait pas, le code se casse. Ainsi, faites-le toujours comme ceci:

send(&foo, sizeof foo);

Maintenant vous êtes protégé. Bien sûr, vous dupliquez le nom de la variable, mais qui a une forte probabilité de rupture d'une façon que le compilateur peut détecter, si vous le changez.

38
répondu unwind 2008-10-15 10:11:57
int size = (&arr)[1] - arr;

Découvrez ce lien pour l'explication

33
répondu Arjun Sreedharan 2014-01-10 08:50:34

Vous pouvez utiliser sizeof operator mais cela ne fonctionnera pas pour les fonctions car il prendra la référence du pointeur vous pouvez faire ce qui suit pour trouver la longueur d'un tableau:

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

Code trouvé à l'origine ici: C programme pour trouver le nombre d'éléments dans un tableau

21
répondu Mohd Shibli 2017-11-18 11:55:46

Si vous connaissez le type de données du tableau, vous pouvez utiliser quelque chose comme:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);

Ou si vous ne connaissez pas le type de données du tableau, vous pouvez utiliser quelque chose comme:

noofele = sizeof(arr)/sizeof(arr[0]);

Remarque: Cette chose ne fonctionne que si le tableau n'est pas définie au moment de l'exécution (comme malloc) et le tableau n'est pas passé dans une fonction. Dans les deux cas, arr (nom du tableau) est un pointeur.

19
répondu Abhitesh khatri 2014-09-08 09:32:49

La macro ARRAYELEMENTCOUNT(x), que tout le monde utilise évalue incorrectement. Ceci, de manière réaliste, est juste une question sensible, car vous ne pouvez pas avoir d'expressions qui aboutissent à un type' array'.

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);

en Fait évalue que:

(sizeof (p + 1) / sizeof (p + 1[0]));

Considérant ce qui suit

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);

, Il évalue correctement à:

(sizeof (p + 1) / sizeof (p + 1)[0]);

Cela n'a vraiment pas beaucoup à voir avec la taille des tableaux explicitement. Je viens de remarquer beaucoup d'erreurs en n'observant pas vraiment comment le C préprocesseur fonctionne. Vous enveloppez toujours le paramètre macro, pas une expression dans pourrait être impliquée dans.


C'est correct; mon exemple était mauvaise. Mais c'est exactement ce qui devrait arriver. Comme je l'ai mentionné précédemment, p + 1 finira comme un type de pointeur et invalidera la macro entière (comme si vous essayiez d'utiliser la macro dans une fonction avec un paramètre de pointeur).

À la fin de la journée, dans cette particulier exemple, le défaut n'a pas vraiment d'importance (donc, je perds juste le temps de tout le monde; huzzah!), parce que vous n'avez pas d'expressions avec un type de 'array'. Mais vraiment le point sur les subtilités d'évaluation du préprocesseur, je pense est important.

15
répondu Peter Mortensen 2017-03-09 04:31:14

Pour les tableaux multidimensionnels c'est un peu plus compliqué. Souvent, les gens définissent des constantes Macro explicites, c'est-à-dire

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

Mais ces constantes peuvent aussi être évaluées au moment de la compilation avec sizeof :

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

Notez que ce code fonctionne en C et c++. Pour les tableaux de plus de deux dimensions, utilisez

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

Etc., à l'infini.

14
répondu Andreas Spindler 2016-09-08 10:25:52

Taille d'un tableau en C:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type
13
répondu Yogeesh H T 2017-03-09 04:34:26
sizeof(array) / sizeof(array[0])
11
répondu Ted Percival 2008-09-01 06:50:31
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
10
répondu Andy Nugent 2016-09-12 14:54:31

"vous avez introduit une façon subtile de vous tirer dans le pied"

C les tableaux 'natifs' ne stockent pas leur taille. Il est donc recommandé d'enregistrer la longueur du tableau dans une variable/const séparée, et de le transmettre chaque fois que vous passez le tableau, c'est-à-dire:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

Vous devriez toujours éviter les tableaux natifs (sauf si vous ne pouvez pas, auquel cas, faites attention à votre pied). Si vous écrivez C++, utilisez le conteneur' vector ' de STL . "Par rapport aux tableaux, ils fournissent presque la même performance", et ils sont beaucoup plus utiles!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  

// push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)
    numbers.push_back(i);

// Determine the size of the array
cout << numbers.size();

Voir: http://www.cplusplus.com/reference/stl/vector/

8
répondu Ohad 2014-09-08 09:29:56

@ Magnus: la norme définit sizeof comme donnant le nombre d'octets dans l'objet et que sizeof (char) est toujours un. Le nombre de bits dans un octet est spécifique à l'implémentation.

Modifier: norme ANSI C++ Section 5.3.3 Sizeof:

L'opérateur sizeof donne le nombre d'octets dans la représentation d'objet de son opérande. [...] sizeof (char), sizeof (char signé) et sizeof (unsigned char) sont 1; le résultat de sizeof appliquer à tout autre type fondamental est la mise en œuvre définies.

Section 1.6 le modèle de mémoire c++:

L'Unité de stockage fondamentale dans le modèle de mémoire c++ est l'octet. Un octet est au moins assez grand pour contenir n'importe quel membre du jeu de caractères d'exécution de base et est composé d'une séquence contiguë de bits, dont le nombre est défini par l'implémentation.

5
répondu Skizz 2012-07-03 14:32:40

@Skizz: je suis sûr d'avoir raison, bien que la meilleure "source" que je puisse vous donner en ce moment soit Wikipedia, tirée de l'article sur sizeof:

Wikipedia a tort, Skizz a raison. sizeof (char) est 1, par définition.

Je veux dire, Il suffit de lire L'entrée Wikipedia de très près pour voir que c'est faux. les "multiples de char". sizeof(char) ne peut jamais être quoi que ce soit autre que "1". Si c'était, disons, 2, cela signifierait que sizeof(char) était deux fois la taille de char!

4
répondu DrPizza 2013-02-28 15:05:17

Si vous voulez vraiment faire cela pour passer votre tableau, je suggère d'implémenter une structure pour stocker un pointeur sur le type que vous voulez un tableau et un entier représentant la taille du tableau. Ensuite, vous pouvez transmettre cela à vos fonctions. Il suffit d'attribuer la valeur de la variable de tableau (pointeur sur le premier élément) à ce pointeur. Ensuite, vous pouvez aller Array.arr[i] pour obtenir le i-ème élément et utiliser Array.size pour obtenir le nombre d'éléments dans le tableau.

J'ai inclus un code pour vous. Il n'est pas très utile mais vous pouvez l'étendre avec plus de fonctionnalités. Pour être honnête, si ce sont les choses que vous voulez vous devez cesser d'utiliser C et utiliser une autre langue avec ces fonctionnalités intégrées.

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}
4
répondu Joel Dentici 2013-06-13 14:37:17

La meilleure façon est d'enregistrer ces informations, par exemple, dans une structure:

typedef struct {
     int *array;
     int elements;
} list_s;

Implémentez toutes les fonctions nécessaires telles que créer, détruire, vérifier l'égalité et tout ce dont vous avez besoin. Il est plus facile de passer en paramètre.

3
répondu Paulo Pinheiro 2016-02-17 14:35:27

La fonction sizeof renvoie le nombre d'octets utilisés par votre tableau dans la mémoire. Si vous voulez calculer le nombre d'éléments dans votre tableau, vous devez diviser ce nombre avec le type de variable sizeof du tableau. Disons int array[10];, si le type de variable entier dans votre ordinateur est 32 bits (ou 4 octets), afin d'obtenir la taille de votre tableau, vous devriez faire ce qui suit:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
3
répondu Keivan 2018-08-20 15:25:43

Vous pouvez utiliser l'opérateur &. Voici le code source:

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};

Voici l'exemple de sortie

1549216672
1549216712
---- diff----
4
The size of array a is 10
1
répondu Shih-En Chou 2014-10-06 02:42:38
 int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
 int len = (int) sizeof(arr) / sizeof(*arr);
 printf("%d\n", len);
-1
répondu LinconFive 2018-09-29 06:45:26