Je me demande pourquoi ce type de code peut obtenir la taille du tableau de test? Je ne connais pas la grammaire du modèle. Peut-être que quelqu'un pourrait expliquer la signification du code ci-dessous template<typename,size_t>
. En outre, un lien de référence est également préféré.
#define dimof(array) (sizeof(DimofSizeHelper(array)))
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
void InitDynCalls()
{
char test[20];
size_t n = dimof(test);
printf("%d", n);
}
c++
visual-c++
Démon de l'ombre
la source
la source
std::array
oustd::vector
....Réponses:
C'est en fait très difficile à expliquer, mais je vais essayer ...
Tout d'abord,
dimof
vous indique la dimension ou le nombre d'éléments dans un tableau. (Je crois que "dimension" est la terminologie préférée dans les environnements de programmation Windows).Ceci est nécessaire car
C++
etC
ne vous donne pas de méthode native pour déterminer la taille d'un tableau.Souvent, les gens supposent que
sizeof(myArray)
cela fonctionnera, mais cela vous donnera en fait la taille en mémoire, plutôt que le nombre d'éléments. Chaque élément prend probablement plus d'un octet de mémoire!Ensuite, ils pourraient essayer
sizeof(myArray) / sizeof(myArray[0])
. Cela donnerait la taille en mémoire du tableau, divisée par la taille du premier élément. C'est ok, et largement utilisé dans leC
code. Le problème majeur avec cela est qu'il semble fonctionner si vous passez un pointeur au lieu d'un tableau. La taille d'un pointeur en mémoire sera généralement de 4 ou 8 octets, même si ce qu'il désigne pourrait être un tableau de 1000 éléments.Donc, la prochaine chose à essayer
C++
est d'utiliser des modèles pour forcer quelque chose qui ne fonctionne que pour les tableaux, et donnera une erreur de compilation sur un pointeur. Cela ressemble à ceci:Le modèle ne fonctionnera qu'avec un tableau. Il déduira le type (pas vraiment nécessaire, mais doit être là pour que le modèle fonctionne) et la taille du tableau, puis il retourne la taille. La façon dont le modèle est écrit ne peut pas fonctionner avec un pointeur.
Habituellement, vous pouvez vous arrêter ici, et cela se trouve dans le C ++ Standard Libary as
std::size
.Attention: ci-dessous, il pénètre dans le territoire de l'avocat de la langue poilue.
C'est assez cool, mais échoue toujours dans un cas de bord obscur:
Notez que le tableau
x
est déclaré , mais non défini . Pour appeler une fonction (ieArraySize
) avec elle,x
doit être défini .Vous ne pouvez pas lier cela.
Le code que vous avez dans la question est un moyen de contourner cela. Au lieu d'appeler réellement une fonction, nous déclarons une fonction qui retourne un objet exactement de la bonne taille . Ensuite, nous utilisons l'
sizeof
astuce à ce sujet.Il semble que nous appelions la fonction, mais
sizeof
est purement une construction de compilation, donc la fonction n'est jamais réellement appelée.Notez que vous ne pouvez pas réellement renvoyer un tableau à partir d'une fonction, mais vous pouvez renvoyer une référence à un tableau.
Ensuite ,
DimofSizeHelper(myArray)
est une expression dont le type est un tableau sur l'N
char
art. L'expression n'a pas besoin d'être exécutable, mais elle a du sens au moment de la compilation.Par conséquent
sizeof(DimofSizeHelper(myArray))
, vous indiquera la taille au moment de la compilation de ce que vous obtiendriez si vous appeliez réellement la fonction. Même si nous ne l'appelons pas vraiment.Ne vous inquiétez pas si ce dernier bloc n'a aucun sens. C'est une astuce bizarre pour contourner un cas de bord bizarre. C'est pourquoi vous n'écrivez pas vous-même ce type de code et laissez les développeurs de bibliothèques s'inquiéter de ce genre de non-sens.
la source
DimofSizeHelper
est une fonction modèle qui prend unT(&)[N]
paramètre - alias une référence à un C-tableau de N éléments de typeT
et renvoie unchar (&)[N]
aka une référence à un tableau de N caractères. En C ++, un caractère est un octet déguisé etsizeof(char)
est garanti1
par la norme.n
se voit attribuer la taille du type de retour deDimofSizeHelper
,sizeof(char[N])
qui estN
.C'est un peu compliqué
et inutile. La façon habituelle de le faire était:Depuis C ++ 17, cela n'est également pas nécessaire, comme nous l'avons
std::size
fait, mais de manière plus générique, être en mesure d'obtenir la taille de n'importe quel conteneur de style stl.Comme l'a souligné BoBTFish, il est nécessaire pour un cas de bord.
la source
std::extent
depuis C ++ 11 qui est le temps de compilation.