J'ai écrit une fonction Array_length, comme ceci:
int k = sizeof(arr)/sizeof(int);
printf("%i", k);
14 Réponses :
Les longueurs de tableau de calcul, en C, sont au mieux problématiques.
Le problème avec votre code ci-dessus, est-ce que lorsque vous faites: p> tu es vraiment Il suffit de passer dans un pointeur comme "A", donc Vous pouvez (potentiellement) faire cela comme une macro au lieu d'une fonction, mais cela a ses propres problèmes ... (cela l'étouffe complètement, vous obtenez donc le même comportement que votre Tailleof (a) code> est Tailleof (int *) code>. Si vous êtes sur un système 64 bits, vous obtiendrez toujours 2 pour tailleOf (a) / sizeof (int) code> à l'intérieur de la fonction, puisque le pointeur sera 64bits. P> int k = ... code> bloc, cependant.) p> p>
N'est-il pas possible pour sizeof (int) == tailleof (int *) code> sur un système 64 bits? La taille de int code> est en fonction de la mise en œuvre, mais toujours au moins 32 bits, ou j'ai donc pensé.
Oui, mais il n'y a pas de compilateur C sur Terre qui définit Int = 64 bits. Sauf si vous écrivez ou en patch un.
@DeMlax: c'est possible, mais je ne sais aucun que cela fait ça. MS + GNU + Intel + La plupart des autres compilateurs Set Tiplôme de (int) == 32 ...
Ma compréhension est que la plupart des systèmes UNIX 64 bits utilisent le modèle ILP64 code> où int code> est 64 bits ( UNIX.ORG/VERSION2/WHTSNEW/LP64_WP.HTML ). Bien sûr, depuis que j'ai peu d'expérience sur des boîtes Unix, je pourrais me tromper. (Windows utilise le modèle LLP64 où int code> est 32 bits: blogs.msdn.com/oldnewthing/archive/2005/01/31/363790.aspx ).
Comment les longueurs de tableau de calcul peuvent-elles être "problématiques au mieux" quand elles sont complètement, totalement précises et sans ambiguïté par la norme de langage C?
@ Chris-Dodd Je vois pourquoi ils l'ont nommé cela.
Utilisez une macro ...
#define SIZEOF_ARRAY( arr ) sizeof( arr ) / sizeof( arr[0] )
Naturellement ... mais c'est juste l'effet secondaire des macros. Cela nécessite que l'utilisateur les utilise de manière appropriée.
Il a la vertu d'éventuellement fonctionner correctement, contrairement à la fonction.
@David: Et n'est-ce pas ce qui est le plus important: le code qui fonctionne potentiellement correctement, parfois?
Le problème est la compréhension de l'OP des tableaux et des pointeurs, que la réponse ci-dessus n'explique pas.
@Blueraja: code qui fonctionne lorsqu'il est invoqué correctement i> peut être considéré comme suffisant pour votre nécessité.
@Blueraja: Bon point, mais cela bat sans doute du code qui ne fonctionnera certainement pas. Homme, je suis content C ++ a std :: vecteur code>.
@Michael: J'ai pensé à bracker la macro expansion mais n'a pas vu le point. Une déclaration plus complexe ne serait pas une macro et que le code ne pouvait donc pas travailler de toute façon ...
@Goz: Mis à part le fait qu'une expansion macro doit toujours être enfermée dans des parens, sauf si cela ne cassait spécifiquement l'utilisation prévue de la macro (je me permettait également de sauter les parens si la macro est un nombre simple, mais même alors je Parfois, on se sent comme je fais quelque chose de mal), si votre macro comme donnée est utilisée dans le cadre d'une autre expression, cela pourrait introduire un débordement ou une troncature involontaire (en particulier si la multiplication ou la division est impliquée).
@Michael: Mais l'entrée serait invalide pour une telle macro. Alors, quel est le point? Une expansion macro ne devrait être conçue qu'avec des parenthèses si c'est logique de le faire. Dans ce cas, je ne peux pas penser à un seul cas où il serait logique de le faire ...
En général, il est impossible de mesurer la taille de la matrice C. Dans votre fonction principale, le compilateur compte les éléments que vous avez écrites entre les accolades pour vous, de sorte que vous déclarez vraiment Dans votre fonction, cependant, C'est l'une des nombreuses raisons d'utiliser int arr [7] code >. Cela a la taille que vous attendez. p>
int A [] code> est équivalent à int * a code> - un pointeur sur un entier. vous em> sais que c'est un tableau, il y a donc plus d'entiers suivants, mais votre fonction array_length CODE> peut être transmise tout pointeur entier em>, donc il ne peut pas em> savoir. p>
std :: vecteur code> au lieu des matrices brutes autant que possible. p>
En disant que cela est impossible, c'est un peu d'exagération - il y a certainement des problèmes, et cela ne peut pas toujours être fait proprement. Mais il y a des techniques qui fonctionnent assez souvent pour être très utiles malgré les inconvénients.
Aah, je suis tellement habitué à C ++ ... et oui, je sais qu'il y a des techniques macro-macro-ciblées comme indiquées par d'autres personnes, mais elles semblent extrêmement problématiques pour moi. Je n'aime pas l'idée d'une "fonction" (macro) qui fonctionne pour des variables déclarées dans la même portée, mais pas pour les paramètres. Ensuite, chaque fois que vous souhaitez l'utiliser, vous devez vous rappeler de vérifier où vous avez déclaré la variable que vous l'appelez. Si vous oubliez, cela compilera simplement bien, mais donner des résultats flagrant de mauvais résultats.
C'est un point de vue légitime. Personnellement, je trouve l'utilité de la macro pour l'emporter sur les inconvénients.
essayer _countof c'est défini dans Winnt.h comme
Votre fonction ne fonctionnera pas. Les tableaux C et C sont des types différents, mais la matrice dégénérera dans un pointeur si vous le regardez drôle.
Dans ce cas, vous passez la matrice comme un paramètre, et cela se transforme en un pointeur dans l'appel. , donc vous mesurez le Le seul moyen de faire ce travail est d'utiliser une macro: p> < Pré> xxx pré> et qui ne fonctionnera que si tailleof (int *) / sizeof (int) code>. p> x code> est déclaré dans cette portée comme une matrice et non comme un pointeur. P> P>
La procédure générale pour calculer le nombre d'éléments dans un tableau est Écrire une fonction Pour calculer la longueur d'un tableau transmis comme un argument est condamné à une défaillance, car la fonction reçoit est un pointeur, pas un tableau. Lorsque vous appelez votre fonction avec une expression de tableau comme argument, l'expression de tableau aura son type converti implicitement de «une matrice de t» à «pointeur sur T» et sa valeur sera définie sur le premier élément de la matrice. Votre fonction ne voit pas un objet de tableau; Il voit un pointeur. p>
Dans le contexte d'une déclaration de paramètre de fonction, Tailleofarr / Tailleofr Arr [0] Code> (ou Tailleofarr / Taille de * Arr code>). Cela dit ... p>
int a [] code> est exactement le même que int * a code>, mais c'est seulement em> vrai Pour les déclarations de paramètres de fonction (rien ne me rendrait plus heureux que de voir le premier formulaire banni de toutes les futures versions de C, mais cela ne va pas arriver). p>
Référence du tableau résoudra ceci, bien que je ne suggérais jamais d'utiliser une telle chose (puisque elle ne fonctionnera que si vous transmettez toujours la référence ou utilisez-la dans la portée dans laquelle le tableau a été défini):
template <typename T, unsigned N>
unsigned mysize(T (&)[N]) {
return N;
}
MHM, bon point: désolé, je n'ai pas remarqué cela. Je quitterai le commentaire Tho, puisqu'il peut-être qu'il est capable d'utiliser c ++ aussi.
S'il peut utiliser C ++, il devrait préférer le format CANONICAL STD :: Taille_T (Taille Taille_T (T (&) [N]) {Retour N;} Code> Version Pour avoir une vérification de type plus forte.
Un inconvénient potentiel sur les solutions C ++ qui renvoient une valeur d'une fonction sont qu'ils ne sont pas des constantes de temps compilé (je comprends que ce n'est pas ce que l'OP cherchait, mais c'est quelque chose à prendre conscience). Pour une solution 100% compilée et Typeafe (mais nécessite toujours un peu de macro utilisée pour avoir la facilité d'utilisation souhaitée), consultez l'implémentation de Microsoft à l'aide de modèles C ++ à Winnt.h
@Michael Burr: Tous les tableaux ne sont pas créés au moment de la compilation, la taille devrait donc être calculée à l'exécution de toute façon.
@DeMlax: Les solutions de fonction de modèle indiquées ici ne compileraient pas (même si seulement pour évaluer au moment de l'exécution) pour les tableaux dont la taille n'est pas connue de manière statique au moment de la compilation.
@Michael Burr: Je ne dis pas qu'ils étaient, je disais juste que toutes les tailles de réseau ne peuvent pas être déterminées lors de la compilation.
@DeMlax: Je suppose que je pensais que vous essayiez de souligner que les solutions C ++ ont eu un avantage pour cette situation.
Le problème est que les paramètres de fonction ne peuvent pas vraiment être des tableaux, même si C vous permet de faire une déclaration qui ressemble à un. Le paramètre finit par être un simple pointeur. Je l'ai dit ailleurs :
Cela revient au fait que les paramètres du tableau clair en C / C ++ sont une fiction - ils sont vraiment des pointeurs. Les paramètres du réseau doivent être évités autant que possible -. ils les questions vraiment juste Confuse p> Blockquote>
Voilà pourquoi ce type de construction pour retourner le nombre d'éléments dans une extrémité du tableau en étant une macro dans C. Voir cette réponse précédente SO pour ce que je pense est un bon (si compliqué) la mise en œuvre de la macro : p>
- y at-il une fonction standard en C qui retourne la longueur d'un tableau? li> Ul>
Pour plus de commodité, voici la macro: p>
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
En C ++, il est possible d'utiliser des modèles comme illustré dans une autre réponse. J'ai un exemple (volé de Microsoft) dans cette réponse, Stackoverflow.com/questions/95500/... , mais j'ai décidé de garder cette réponse simple car elle semblait être spécifique.
La réponse simple à votre question est la suivante: il n'ya aucun moyen d'écrire la fonction Vous avez fait l'erreur commune des érayes de confusion et des pointeurs de C. En C, le nom d'un tableau, dans la plupart des cas em> est équivalent à un pointeur à son premier élément. Votre fonction qui, essentiellement divise la taille de MAINTENANT, comment pouvez-vous déterminer sa taille correctement en dehors de la fonction ? La réponse est que Enfin, pour déterminer la taille d'un tableau array_length code>. Vous pourrait em> pouvoir s'en tirer avec une définition de macro, mais cela dépend du contexte dans lequel vous utiliserez la macro. array_length code> reçoit un tableau A code> dans un tel contexte. En d'autres termes, il est impossible de passer un tableau en tant que tableau em> dans C. Votre fonction est comme si elle est définie comme si elle est définie comme suit: p> int * code> par la taille de int code>. En outre, par la description ci-dessus, il est impossible em> de connaître la taille d'un tableau en C dans une fonction. P> Tailleof code> est l'un des cas où le nom d'un tableau pas em> réduit à un pointeur à son premier élément. J'ai expliqué les différences plus élaborées dans cette réponse . Notez également que malgré les apparitions, Tailleof code> est un opérateur, pas une fonction (comme nous venons d'apprendre, il ne peut pas em> être une fonction, car alors cela ne sera pas capable Pour calculer la taille d'un tableau). p> A code> de tout type t code>, je préfère: P> size_t sz = sizeof a / sizeof a[0];
int ARRA [peu importe] la liste de fonctions intérieures Définit un pointeur fort>, pas un tableau. Par conséquent, les informations sur la longueur sont perdues pour toujours. P>
Pourquoi!? P>
Pour voir pourquoi, vous devez comprendre ce que C est tout à propos. C ne copie jamais des morceaux complexes autour implicitement. Alors, quand vous dites "passez-moi un tableau", cela signifie que "je veux transmettre une adresse, quel nom de tableau est généralement". p>
Ce n'est pas un inconvénient. Si vous voulez plus, vous devrez le transmettre manuellement. La récompense est que vous savez exactement ce qui se passe au niveau de la machine, vous donnant des performances et d'autres avantages. Voici comment vous pouvez avoir un langage de programmation universel à toutes fins. P>
La syntaxe "INT A []" utilisé comme argument de fonction est équivalente à "int * a".
cette syntaxe: p>
int arr [] = {3,4,5,6,1,7,2}; p> BlockQuote>
ne fonctionne que lors de la compilation. p>
Donc, alors que vous pouvez écrire: int arr [] = {3,4,5,6,1,7,2}; printf ("taille =% d \ n", tailleOf (arr)); p>
Cela ne fonctionnera que lors de la compilation. P>
Une façon d'aller dans ce sens est de faire le tour de ce Tableaux dynamiques et créez votre propre type de tableau. p>
par exemple p>
xxx pré> et utilisez mulloc pour définir sa taille. Vous pouvez le remplir à l'aide des élipités. P>
populate_array(array, ...);
Il n'y a aucun moyen de déterminer la taille d'un tableau transmis dans une fonction comme celle-ci Il n'y a pas assez d'informations au moment de la compilation ou au moment de l'exécution pour le calculer P > La taille de tours ne fonctionne que dans les emplacements source où la taille de la matrice est spécifiée p> p>
Cela fonctionne assez bien:
int A[5] = {10, 20, 30, 40, 3};
int length = sizeof(A) / sizeof(A[0]); // prints 5
J'ai trouvé c'était un piège fait par notre compilateur C! (Alors, c'est une norme de CPL? C99 ou autre chose?) J'ai écrit le code suivant dans Visual Studio 2010 sur la plate-forme X86.
int * a = NULL;
013830FE mov dword ptr [a],0
int len = 0;
01383105 mov dword ptr [len],0
a = (int *) calloc(7, sizeof(int));
0138310C mov esi,esp
0138310E push 4
01383110 push 7
01383112 call dword ptr [__imp__calloc (13882CCh)]
01383118 add esp,8
0138311B cmp esi,esp
0138311D call @ILT+300(__RTC_CheckEsp) (1381131h)
01383122 mov dword ptr [a],eax
len = sizeof(a) / sizeof(a[0]);
01383125 mov dword ptr [len],1 // Hey!
return 0;
0138312C xor eax,eax
}
Bien que certaines personnes ci-dessous aient fourni une macro qui fonctionne, il est important d'internaliser que c est différent des autres langues (Java, C #, etc.), des tableaux sont vraiment des pointeurs sur un bloc de mémoire et c'est à vous de décider garder une trace de la longueur i>. Si vous «obtenez» cela, cela fera travailler avec C beaucoup plus facile.