Question Pourquoi la taille d'un paramètre de tableau n'est-elle pas la même que celle de main?


Pourquoi la taille d'un tableau n'est-elle pas envoyée en paramètre de la même manière que dans main?

#include <stdio.h>

void PrintSize(int p_someArray[10]);

int main () {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* As expected, 40 */
    PrintSize(myArray);/* Prints 4, not 40 */
}

void PrintSize(int p_someArray[10]){
    printf("%d\n", sizeof(p_someArray));
}

95
2017-12-29 15:12


origine


Réponses:


Non, type de tableau est implicitement converti en type de pointeur lorsque vous le transmettez à une fonction.

Alors,

void PrintSize(int p_someArray[10]) {
    printf("%zu\n", sizeof(p_someArray));
}

et

void PrintSize(int *p_someArray) {
    printf("%zu\n", sizeof(p_someArray));
}

sont équivalents. Donc, ce que vous obtenez est la valeur de sizeof(int*)


95
2017-12-29 17:23



C'est un pointeur, c'est pourquoi il s'agit d'une implémentation commune pour passer la taille du tableau en second paramètre à la fonction


17
2017-12-29 17:21



Comme d'autres l'ont indiqué, les tableaux se désintègrent en pointeurs vers leur premier élément lorsqu'ils sont utilisés comme paramètres de fonction. Il convient également de noter que sizeof n'évalue pas l'expression et ne nécessite pas de parenthèses lorsqu'il est utilisé avec une expression. Votre paramètre n'est donc pas utilisé du tout, vous pouvez donc écrire le sizeof avec le type plutôt que la valeur.

#include <stdio.h>

void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );

int main ()
{
    int myArray[10];
    printf ( "%d\n", sizeof myArray ); /* as expected 40 */
    printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */
    PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
    PrintSize2 ( 0 ); /* prints 40, someArray unused */
}

void PrintSize1 ( int someArray[][10] )
{
    printf ( "%d\n", sizeof someArray[0] );
}

void PrintSize2 ( int someArray[10] )
{
    printf ( "%d\n", sizeof ( int[10] ) );
}

16
2017-12-29 20:09



Vous devrez donc passer la longueur du tableau en second paramètre. Lorsque vous écrivez du code, dans lequel vous déclarez à la fois un tableau de taille constante et que vous transmettez ce tableau à une fonction, il est pénible que la constante de longueur du tableau apparaisse à plusieurs endroits dans votre code ...

K & R à la rescousse:

#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) 

Donc maintenant vous pouvez faire par exemple:

int a[10];
...
myfunction(a, N_ELEMENTS(a));

12
2017-12-29 15:15



Parce que les tableaux se dégradent en pointeurs lorsqu'ils sont passés en paramètres. C'est comme ça que C fonctionne, même si vous pouvez passer des "tableaux" en C ++ par référence et surmonter ce problème. Notez que vous pouvez passer des tableaux de tailles différentes à cette fonction:

 // 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);

5
2018-06-23 09:34



Dans c ++, vous pouvez passer un tableau par référence à cet effet:

void foo(int (&array)[10])
{
    std::cout << sizeof(array) << "\n";
}

4
2017-10-05 10:15



Le comportement que vous avez trouvé est en fait une grosse verrue en langage C. Chaque fois que vous déclarez une fonction qui prend un paramètre de tableau, le compilateur vous ignore et change le paramètre en un pointeur. Donc, ces déclarations se comportent toutes comme la première:

void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)

a sera un pointeur sur int dans les quatre cas. Si vous passez un tableau à func, il se transformera immédiatement en un pointeur vers son premier élément. (Sur un système 64 bits, un pointeur 64 bits est deux fois plus grand qu'un int 32 bits, donc votre ratio sizeof renvoie 2.)

Le seul objectif de cette règle est de maintenir la compatibilité ascendante avec les compilateurs historiques qui ne prenaient pas en charge les valeurs d'agrégat de passage en tant qu'arguments de fonction.

Cela ne signifie pas qu'il est impossible de passer un tableau à une fonction. Vous pouvez contourner cette verrue en incorporant le tableau dans une structure (ceci est essentiellement le but de std :: array de C ++ 11):

struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0]));  /* prints 5 */
}

ou en passant un pointeur sur le tableau:

void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints 5 */
}

Si la taille du tableau n'est pas une constante à la compilation, vous pouvez utiliser la technique du pointeur vers le tableau avec les tableaux de longueur variable C99:

void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints n */
}

4
2017-12-29 15:16



En langage C, il n’existe pas de méthode pour déterminer le taille d'un tableau inconnu, de sorte que la quantité doit être passé ainsi qu'un pointeur vers le premier élément.


3
2017-12-29 15:44



Vous ne pouvez pas passer de tableaux à des fonctions.

Si vous vouliez vraiment imprimer la taille, vous pourriez passer un pointeur sur un tableau, mais ce ne serait pas du tout générique car vous devez également définir la taille du tableau pour la fonction.

#include <stdio.h>

void PrintSize(int (*p_anArray)[10]);

int main(void) {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* as expected 40 */
    PrintSize(&myArray);/* prints 40 */
}

void PrintSize(int (*p_anArray)[10]){
    printf("%d\n", (int) sizeof(*p_anArray));
}

2
2017-12-29 15:17



Le comportement est par conception.

La même syntaxe dans la déclaration de paramètre de fonction signifie une chose complètement différente que dans la définition de variable locale.

La raison est décrite dans d'autres réponses.


0
2017-12-18 09:32



En langage C, lorsque vous transmettez le tableau en tant qu’argument à la fonction, il est automatiquement converti en pointeur, le passage d’un tableau à une autre fonction est connu sous le nom d’appel par référence. C’est la raison pour laquelle la fonction appelée ne reçoit que le pointeur qui pointe vers le premier élément de la fonction.

fun (int a []) est similaire à fun (int * a);

Ainsi, lorsque vous imprimez la taille du tableau, il affiche la taille du premier élément.


0
2018-06-11 00:17