La macro standard de taille de tableau qui est souvent enseignée est la suivante
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
ou toute autre formation équivalente. Cependant, ce genre de chose réussit silencieusement lorsqu'un pointeur est passé, et donne des résultats qui peuvent sembler plausibles à l'exécution jusqu'à ce que les choses s'effondrent mystérieusement.
Il n'est que trop facile de commettre cette erreur : une fonction qui possède une variable locale de type tableau est remaniée, déplaçant une partie de la manipulation du tableau dans une nouvelle fonction appelée avec le tableau en tant que paramètre.
La question est donc de savoir s'il existe une macro "sanitaire" pour détecter l'utilisation abusive de la ARRAYSIZE
en C, de préférence au moment de la compilation ? En C++, nous utiliserions simplement un modèle spécialisé pour les arguments de type tableau uniquement ; en C, il semble que nous ayons besoin d'un moyen de distinguer les tableaux et les pointeurs. (Si je voulais rejeter les tableaux, par exemple, je ferais simplement e.g. (arr=arr, ...)
car l'assignation d'un tableau est illégale).
1 votes
Cela va être difficile, car les tableaux se transforment en pointeurs dans pratiquement tous les contextes.
1 votes
Pourquoi quelqu'un aurait-il besoin d'une telle macro ? Cela ne fonctionne qu'avec des tableaux qui ont été définis par une taille fixe dans le code, pourquoi auriez-vous besoin de calculer ce que vous savez avoir écrit ? Si la réponse est "peut-être que vous êtes dans une autre partie de votre code et que vous n'avez plus cette information", ma question suivante est : comment est-ce possible avec le tableau qui ne se décompose pas en pointeur, dans un morceau de code non étrange et non spécifiquement conçu pour que cela se produise ?
1 votes
@Eregrith:cela fonctionne aussi avec les VLA, les réseaux de longueur variable. Mais c'est un détail. Cela "ne fonctionne qu'avec les tableaux dont la définition est dans le champ d'application" est plus proche de la réalité, mais pas très différent de ce que vous avez dit.
7 votes
@Eregrith Par extension, ce point de vue pourrait tout aussi bien être "pourquoi quelqu'un aurait-il besoin d'un quelconque calcul à la compilation ou d'une quelconque métaprogrammation, jamais" ? L'idée que "vous savez ce que vous avez écrit" est à la fois ridicule et inutile. Aucune loi ne stipule que vous devez l'écrire à la main.
0 votes
Les VLA sont de toute façon attribués avec un paramètre de taille donné et, conformément à la section C99, les VLA sont attribués avec un paramètre de taille donné. 6.19 Tableaux de longueur variable vous savez qu'en dehors de la portée de la fonction déclarante, ils sont désalloués. Cela dit, vous pourriez facilement transmettre le paramètre définissant la taille.
0 votes
@Leushenko Je suis désolé mais le calcul à la compilation doit se faire sur non connu antérieurement données. Écrivriez-vous vraiment
char a[100];
puis deux lignes en dessousprintf("My array is of length %d\n", ARRAYZISE(a));
? Le feriez-vous vraiment ? D'un autre côté, vous ne pouvez pas deviner quelle serait, par exemple, la taille saisie par l'utilisateur.0 votes
@Leushenko Et l'idée que "vous savez ce que vous avez écrit" n'est pas inutile du tout. Pourquoi faudrait-il tout recalculer à chaque fois ?
#define ARRAYSIZE 100
char arr[ARRAYSIZE];
et de rouler avec !7 votes
@Eregrith Je ne verrais absolument rien de mal à écrire
char a[MAGIC_STUFF(COMPLICATED(X, Z+FOO(G)))];
et de ne pas vouloir l'écrire à nouveau plus bas. Si l'information et les outils existent, il faut les utiliser.0 votes
@Leushenko Dans ce cas, d'accord, merci.
3 votes
@Eregrith : Au moins deux situations me viennent à l'esprit : (1) La taille du tableau peut ne pas être spécifiée, mais peut être déduite de la liste d'initialisation ; (2) Il peut être utile d'avoir une macro comme
#define SEND_FIXED_COMMAND(cmd) send_command((arr), sizeof (arr))
afin d'éviter d'avoir à spécifier à la fois le nom du tableau et le nom d'une constante donnant la taille du tableau.0 votes
Peut-être en double : stackoverflow.com/questions/12849714/est-ce qu'il y a un moyen sûr d'obtenir un décompte d'éléments pour les tableaux en cm ? En rapport : stackoverflow.com/questions/16794900/validate-an-argument-is-array-type-in-c-pre-processing-macro-on-compile-time/
0 votes
Un autre doublon possible : stackoverflow.com/questions/12784136/reliably-determine-the-number-of-elements-in-an-array?noredirect=1&lq=1
1 votes
Les tableaux de taille 1 sont rares, d'où
#define likely_array(arr) ((sizeof(arr) / sizeof(arr[0]) != 1)
pourrait fonctionner0 votes
Le CCG 8 met en garde contre
-Wall
si elle est utilisée avec un pointeur