Comment trouver le ‘sizeof’ (un pointeur pointant sur un tableau)?

Tout d’abord, voici un code:

int main() { int days[] = {1,2,3,4,5}; int *ptr = days; printf("%u\n", sizeof(days)); printf("%u\n", sizeof(ptr)); return 0; } 

Existe-t-il un moyen de déterminer la taille du tableau pointé par ptr (au lieu de simplement indiquer sa taille, qui est de quatre octets sur un système 32 bits)?

    Non, vous ne pouvez pas. Le compilateur ne sait pas à quoi pointe le pointeur. Il existe des astuces, comme terminer le tableau avec une valeur hors bande connue, puis compter la taille jusqu’à cette valeur, mais cela n’utilise pas sizeof.

    Une autre astuce est celle mentionnée par Zan , qui consiste à cacher la taille quelque part. Par exemple, si vous allouez dynamicment le tableau, allouez un bloc plus grand que celui dont vous avez besoin, rangez la taille dans le premier int et renvoyez ptr + 1 comme pointeur vers le tableau. Lorsque vous avez besoin de la taille, décrémentez le pointeur et regardez la valeur cachée. Rappelez-vous juste de libérer le bloc entier à partir du début, et pas seulement du tableau.

    La réponse est non.”

    Ce que font les programmeurs C, c’est de stocker la taille du tableau quelque part. Cela peut faire partie d’une structure, ou le programmeur peut tromper un peu plus de mémoire que ce que demande malloc () pour stocker une valeur de longueur avant le début du tableau.

    Pour les tableaux dynamics ( malloc ou C ++ new ), vous devez stocker la taille du tableau comme mentionné par d’autres ou créer une structure de gestionnaire de tableaux qui gère l’ajout, la suppression, le comptage, etc. C ++ puisque vous devez essentiellement le construire pour chaque type de baie que vous stockez, ce qui est encombrant si vous devez gérer plusieurs types de baies.

    Pour les tableaux statiques, tels que celui de votre exemple, il existe une macro commune utilisée pour obtenir la taille, mais elle n’est pas recommandée car elle ne vérifie pas si le paramètre est réellement un tableau statique. La macro est utilisée dans le code réel cependant, par exemple dans les en-têtes du kernel Linux, bien que cela puisse être légèrement différent de celui ci-dessous:

     #if !defined(ARRAY_SIZE) #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) #endif int main() { int days[] = {1,2,3,4,5}; int *ptr = days; printf("%u\n", ARRAY_SIZE(days)); printf("%u\n", sizeof(ptr)); return 0; } 

    Vous pouvez google pour des raisons de se méfier des macros comme celle-ci. Faites attention.

    Si possible, le stdlib C ++ tel que vector est beaucoup plus sûr et plus facile à utiliser.

    Il existe une solution propre avec les modèles C ++, sans utiliser sizeof () . La fonction getSize () suivante renvoie la taille de tout tableau statique:

     #include  template size_t getSize(T (&)[SIZE]) { return SIZE; } 

    Voici un exemple avec une structure foo_t :

     #include  template size_t getSize(T (&)[SIZE]) { return SIZE; } struct foo_t { int ball; }; int main() { foo_t foos3[] = {{1},{2},{3}}; foo_t foos5[] = {{1},{2},{3},{4},{5}}; printf("%u\n", getSize(foos3)); printf("%u\n", getSize(foos5)); return 0; } 

    Sortie:

     3 5 

    Pour cet exemple spécifique, oui, il y a, si vous utilisez des typedefs (voir ci-dessous). Bien sûr, si vous le faites de cette façon, vous avez tout aussi bien intérêt à utiliser SIZEOF_DAYS, puisque vous savez à quoi pointe le pointeur.

    Si vous avez un pointeur (void *), tel que retourné par malloc () ou similaire, alors, non, il n’y a aucun moyen de déterminer la structure de données vers laquelle pointe le pointeur et donc aucun moyen de déterminer sa taille.

     #include  #define NUM_DAYS 5 typedef int days_t[ NUM_DAYS ]; #define SIZEOF_DAYS ( sizeof( days_t ) ) int main() { days_t days; days_t *ptr = &days; printf( "SIZEOF_DAYS: %u\n", SIZEOF_DAYS ); printf( "sizeof(days): %u\n", sizeof(days) ); printf( "sizeof(*ptr): %u\n", sizeof(*ptr) ); printf( "sizeof(ptr): %u\n", sizeof(ptr) ); return 0; } 

    Sortie:

     SIZEOF_DAYS: 20 sizeof(days): 20 sizeof(*ptr): 20 sizeof(ptr): 4 

    Il n’y a pas de solution magique. C n’est pas un langage réflexif. Les objects ne savent pas automatiquement ce qu’ils sont.

    Mais vous avez beaucoup de choix:

    1. Evidemment, ajoutez un paramètre
    2. Enveloppez l’appel dans une macro et ajoutez automatiquement un paramètre
    3. Utilisez un object plus complexe. Définissez une structure contenant le tableau dynamic et la taille du tableau. Ensuite, passez l’adresse de la structure.

    Comme toutes les réponses correctes l’ont indiqué, vous ne pouvez pas obtenir cette information à partir de la valeur du pointeur décroché du tableau seul. Si le pointeur décomposé est l’argument reçu par la fonction, la taille du tableau d’origine doit être fournie d’une autre manière pour que la fonction en connaisse la taille.

    Voici une suggestion différente de ce qui a été fourni jusqu’ici, qui fonctionnera: Passez plutôt un pointeur sur le tableau. Cette suggestion est similaire aux suggestions de style C ++, sauf que C ne prend pas en charge les modèles ou les références:

     #define ARRAY_SZ 10 void foo (int (*arr)[ARRAY_SZ]) { printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr)); } 

    Mais, cette suggestion est un peu idiot pour votre problème, puisque la fonction est définie pour connaître exactement la taille du tableau qui est passé (par conséquent, il est inutile d’utiliser sizeof sur le tableau). Ce qu’elle fait, cependant, c’est d’offrir une certaine sécurité. Cela vous interdira de passer dans un tableau de taille indésirable.

     int x[20]; int y[10]; foo(&x); /* error */ foo(&y); /* ok */ 

    Si la fonction est supposée pouvoir fonctionner sur n’importe quelle taille de tableau, vous devrez alors fournir la taille à la fonction en tant qu’information supplémentaire.

    Ma solution à ce problème consiste à enregistrer la longueur du tableau dans un tableau struct comme une méta-information sur le tableau.

     #include  #include  struct Array { int length; double *array; }; typedef struct Array Array; Array* NewArray(int length) { /* Allocate the memory for the struct Array */ Array *newArray = (Array*) malloc(sizeof(Array)); /* Insert only non-negative length's*/ newArray->length = (length > 0) ? length : 0; newArray->array = (double*) malloc(length*sizeof(double)); return newArray; } void SetArray(Array *structure,int length,double* array) { structure->length = length; structure->array = array; } void PrintArray(Array *structure) { if(structure->length > 0) { int i; printf("length: %d\n", structure->length); for (i = 0; i < structure->length; i++) printf("%g\n", structure->array[i]); } else printf("Empty Array. Length 0\n"); } int main() { int i; Array *negativeTest, *days = NewArray(5); double moreDays[] = {1,2,3,4,5,6,7,8,9,10}; for (i = 0; i < days->length; i++) days->array[i] = i+1; PrintArray(days); SetArray(days,10,moreDays); PrintArray(days); negativeTest = NewArray(-5); PrintArray(negativeTest); return 0; } 

    Mais vous devez vous préoccuper de définir la bonne longueur du tableau que vous souhaitez stocker, car il n’est pas possible de vérifier cette longueur, comme l’ont expliqué massivement nos amis.

     int main() { int days[] = {1,2,3,4,5}; int *ptr = days; printf("%u\n", sizeof(days)); printf("%u\n", sizeof(ptr)); return 0; } 

    La taille des jours [] est 20, ce qui ne correspond pas à la taille des éléments * de son type de données. Alors que la taille du pointeur est de 4, peu importe ce qu’il pointe. Parce qu’un pointeur pointe vers un autre élément en stockant son adresse.

    Non, vous ne pouvez pas utiliser sizeof(ptr) pour trouver la taille du tableau ptr pointée.

    Bien que l’allocation de mémoire supplémentaire (plus que la taille du tableau) sera utile si vous souhaitez stocker la longueur dans un espace supplémentaire.

      #define array_size 10 struct { int16 size; int16 array[array_size]; int16 property1[(array_size/16)+1] int16 property2[(array_size/16)+1] } array1 = {array_size, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; #undef array_size 

    array_size passe à la variable size :

     #define array_size 30 struct { int16 size; int16 array[array_size]; int16 property1[(array_size/16)+1] int16 property2[(array_size/16)+1] } array2 = {array_size}; #undef array_size 

    Utilisation est:

     void main() { int16 size = array1.size; for (int i=0; i!=size; i++) { array1.array[i] *= 2; } } 

    Vous pouvez faire quelque chose comme ça:

     int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 }; int *ptr = days + 1; printf("array length: %u\n", ptr[-1]); return 0; 

    Il n’est pas possible de trouver la valeur sizeof du pointeur, car le compilateur ne sait pas combien de temps ce pointeur est en train de pointer. Le pointeur sizeof doit être 2 ou 4 (selon le compilateur).

    salut dans les chaînes il y a un caractère '\0' à la fin donc on peut avoir la taille d’une chaîne avec des fonctions comme strlen Le problème avec un tableau d’entiers par exemple est que tu ne peux pas utiliser une valeur comme valeur finale la solution possible est d’adresser le tableau et d’utiliser comme valeur de fin le pointeur NULL

     /* http://stackoverflow.com/questions/492384/how-to-find-the-sizeof-a-pointer-pointing-to-an-array */ #include  /* the following function will produce the warning: * 'sizeof' on array function parameter 'a' will * return size of 'int *' [-Wsizeof-array-argument] */ void foo( int a[] ) { printf( "%lu\n", sizeof a ); } /* so we have to implement something else one possible * idea is to use the NULL pointer as a control value * the same way '\0' is used in ssortingngs but this way * the pointer passed to a function should address pointers * so the actual implementation of an array type will * be a pointer to pointer */ typedef char * type_t; /* line 18 */ typedef type_t ** array_t; /* * -- -- * -**-**- * -$$$$$- * -999- * -^- * - */ int main( void ) { array_t initialize( int, ... ); /* initialize an array with four values "foo", "bar", "baz", "foobar" * if one wants to use integers rather than ssortingngs than in the typedef * declaration at line 18 the char * type should be changed with int * and in the format used for printing the array values * at line 45 and 51 "%s" should be changed with "%i" */ array_t array = initialize( 4, "foo", "bar", "baz", "foobar" ); int size( array_t ); /* print array size */ printf( "size %i:\n", size( array )); void aprint( char *, array_t ); /* print array values */ aprint( "%s\n", array ); /* line 45 */ type_t getval( array_t, int ); /* print an indexed value */ int i = 2; type_t val = getval( array, i ); printf( "%i: %s\n", i, val ); /* line 51 */ void delete( array_t ); /* free some space */ delete( array ); return 0; } /* the output of the program should be: * size 4: * foo * bar * baz * foobar * 2: baz */ #include  #include  array_t initialize( int n, ... ) { /* here we store the array values */ type_t *v = (type_t *) malloc( sizeof( type_t ) * n ); va_list ap; va_start( ap, n ); int j; for ( j = 0; j < n; j++ ) v[j] = va_arg( ap, type_t ); va_end( ap ); /* the actual array will hold the addresses of those * values plus a NULL pointer */ array_t a = (array_t) malloc( sizeof( type_t *) * ( n + 1 )); a[n] = NULL; for ( j = 0; j < n; j++ ) a[j] = v + j; return a; } int size( array_t a ) { int n = 0; while ( *a++ != NULL ) n++; return n; } void aprint( char *fmt, array_t a ) { while ( *a != NULL ) printf( fmt, **a++ ); } type_t getval( array_t a, int i ) { return *a[i]; } void delete( array_t a ) { free( *a ); free( a ); } /* край */