Calcul de la taille d'un tableau
Je suis en utilisant la macro suivante pour le calcul de la taille d'un tableau:
#define G_N_ELEMENTS(arr) ((sizeof(arr))/(sizeof(arr[0])))
Cependant je vois une différence dans la valeur calculée par ça quand j'évaluer la taille d'un tableau dans une fonction (mauvaise valeur calculée), par opposition à l'endroit où la fonction est appelée (valeur calculée). Code + sortie ci-dessous. Des idées, des suggestions, des conseils et coll. bienvenue.
DP
#include <stdio.h>
#define G_N_ELEMENTS(arr) ((sizeof(arr))/(sizeof(arr[0])))
void foo(int * arr) //Also tried foo(int arr[]), foo(int * & arr)
//- neither of which worked
{
printf("arr : %x\n", arr);
printf ("sizeof arr: %d\n", G_N_ELEMENTS(arr));
}
int main()
{
int arr[] = {1, 2, 3, 4};
printf("arr : %x\n", arr);
printf ("sizeof arr: %d\n", G_N_ELEMENTS(arr));
foo(arr);
}
De sortie:
arr : bffffa40
sizeof arr: 4
arr : bffffa40
sizeof arr: 1
source d'informationauteur
Vous devez vous connecter pour publier un commentaire.
C'est parce que la taille d'un
int *
est la taille d'un int pointeur (4 ou 8 octets sur les plateformes modernes que j'utilise, mais cela dépend entièrement de la plate-forme). Lesizeof
est calculé au moment de la compilation, pas de moment de l'exécution, de sorte que mêmesizeof (arr[])
ne va pas aider parce que vous pouvez appeler lafoo()
fonction au moment de l'exécution avec beaucoup de différentes tailles de tableaux.La taille d'un int tableau est la taille d'un int tableau.
C'est l'un des passages techniques en C/C++ - l'utilisation de tableaux et les pointeurs ne sont pas toujours identiques. Les tableaux seront, dans un grand nombre de circonstances, de la décomposition d'un pointeur vers le premier élément de ce tableau.
Il y a au moins deux solutions, compatible à la fois avec le C et le C++:
{1,2,3,4,-1}
.Ce n'est pas de travail parce que sizeof est calculé au moment de la compilation. La fonction n'a pas d'informations sur la taille de son paramètre (il sait seulement qu'il pointe vers une adresse de mémoire).
Envisager l'utilisation d'un vecteur STL au lieu de cela, ou de passage dans la gamme de tailles des paramètres de fonctions.
En C++, vous pouvez définir G_N_ELEMENTS comme ceci :
Si vous souhaitez utiliser la taille de la matrice au moment de la compilation, voici comment faire :
Grâce j_random_hacker pour la correction de mes erreurs et de fournir des informations supplémentaires.
Notez que même si vous essayer de dire au compilateur C la taille du tableau dans la fonction, il ne prend pas l'astuce (mon
DIM
est équivalent à votreG_N_ELEMENTS
):Cette affiche:
Si vous voulez savoir comment big le tableau est à l'intérieur d'une fonction, passer la taille de la fonction. Ou, en C++, l'utilisation des choses comme la STL
vector<int>
.Edit: C++11 a été introduite depuis cette réponse a été écrite, et il comprend des fonctions pour faire exactement ce que je montre ci-dessous:
std::begin
etstd::fin
. Const versionsstd::cbegin
etstd::cend
vont également dans une version future de la norme C++14?) et peut être dans votre compilateur déjà. Ne même pas songer à l'aide de mes fonctions ci-dessous si vous avez accès à des fonctions standard.J'aimerais revenir un peu sur La réponse de Benoît.
Plutôt que de passer juste l'adresse de départ de la matrice comme un pointeur, ou un pointeur, plus la taille comme d'autres l'ont suggéré, inspirez-vous de la bibliothèque standard et passer deux pointeurs de début et de fin du tableau. Non seulement cela rend votre code plus comme C++ moderne, mais vous pouvez utiliser les algorithmes de la bibliothèque standard sur votre tableau!
Voici une autre définition pour COMMENCER et à la FIN, si les modèles ne fonctionnent pas.
mise à Jour: Le code ci-dessus avec les modèles fonctionne sous MS VC++2005 et GCC 3.4.6, comme il se doit. J'ai besoin d'obtenir un nouveau compilateur.
Je suis aussi de repenser la convention de nommage utilisée ici - modèle de fonctions se font passer comme des macros se sent juste mal. Je suis sûr que je vais l'utiliser dans mon propre code très bientôt, et je pense que je vais utiliser ArrayBegin, ArrayEnd, ArrayConstBegin, et ArrayConstEnd.
Si vous modifiez les foo d'une fonction un peu, il pourrait vous faire sentir un peu plus à l'aise:
C'est ce que le compilateur va voir quelque chose qui est complètement un autre contexte que celui de la fonction.
sizeof(arr) est sizeof(int*), c'est à dire. 4
Sauf si vous avez une très bonne raison pour l'écriture de ce code, NE le font PAS. Nous sommes au 21ème siècle, l'utilisation de std::vector à la place.
Pour plus d'info, voir le C++ FAQ: http://www.parashift.com/c++-faq-lite/containers.html
Rappelez-vous: "les Tableaux sont du mal"
Vous devez seulement appeler sizeof sur le tableau. Lorsque vous appelez sizeof sur le type de pointeur de la taille sera toujours 4 (ou 8, ou quel que soit votre système n').
MSFT la notation hongroise peut être moche, mais si vous l'utilisez, vous ne savez pas à appeler votre macro sur tout ce qui commence par un "p".
Également la caisse de la définition de la ARRAYSIZE() macro dans WinNT.h. Si vous êtes à l'aide de C++, vous pouvez faire des choses bizarres avec des modèles pour la compilation affirme si le faire de cette façon.
Maintenant que nous avons
constexpr
en C++11, le type de sécurité (non-macro) version peut également être utilisée dans une expression constante.Cette échoue à compiler, où il ne fonctionne pas correctement, contrairement à votre macro solution (il ne fonctionnera pas sur les pointeurs par accident). Vous pouvez l'utiliser où une constante de compilation est nécessaire:
Cela étant dit, vous êtes mieux d'utiliser
std::array
pour cette si possible. Ne faites pas attention au gens qui disent utiliserstd::vector
parce que c'est mieux.std::vector
est une autre structure de données avec des forces différentes.std::array
a pas de frais généraux par rapport à un C-gamme de style, mais à la différence de la C-gamme de style, il ne sera pas endommagé à un pointeur à la moindre provocation.std::vector
d'autre part, exige que tous les accès indirects accès (passer par un pointeur) et son utilisation nécessite l'allocation dynamique. Une chose à garder à l'esprit si vous êtes habitué à l'aide de C-style de tableaux est pour être sûr de passerstd::array
à une fonction comme ceci:Si vous ne passez pas par référence, les données sont copiées. Cela suit le comportement de la plupart des bien-conçu types, mais il est différent de C-style des tableaux lorsqu'ils sont passés à une fonction (c'est plus le comportement d'un C-gamme de style à l'intérieur d'une structure (struct).