web-dev-qa-db-fra.com

mise en oeuvre de l'opérateur sizeof

J'ai essayé d'implémenter l'opérateur sizeof .. Je l'ai fait de cette façon ..

#define my_sizeof(x) ((&x + 1) - &x)

Mais il finissait toujours par donner le résultat «1» pour l'un ou l'autre type de données.

Je l'ai ensuite googlé pour cela .. et j'ai trouvé le code typecasted

#define my_size(x) ((char *)(&x + 1) - (char *)&x)

Et le code fonctionne s'il est typé .. Je ne comprends pas pourquoi .. Ce code est également PADDING une STRUCTURE parfaitement ..

Il travaille aussi pour 

#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)

Quelqu'un peut-il expliquer s'il vous plaît comment fonctionne-t-il s'il est catalogué et s'il ne l'est pas?

Merci d'avance..

24

Le résultat de la soustraction de pointeur est en éléments et non en octets. Ainsi, la première expression est évaluée à 1 par définition.

Ceci dit, vous devriez vraiment utiliser des parenthèses dans les macros:

#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)

Sinon, essayer d'utiliser my_sizeof() dans une expression peut entraîner des erreurs.

28
NPE

L'opérateur sizeof fait partie de la spécification du langage C (et C++) et est implémenté à l'intérieur du compilateur (le frontal). Il n’est pas possible de l’implémenter avec d’autres constructions C (à moins que vous utilisiez des extensions GCC comme typeof ) car il peut accepter des types ou des expressions comme opérande, sans créer d’effet secondaire (par exemple, sizeof((i>1)?i:(1/i)) ne plantera pas lorsque i==0 mais votre macro my_sizeof planterait avec une division par zéro). Voir aussi Directives de codage C , et wikipedia .

Vous devriez comprendre C arithmétique de pointeur . Voir par exemple cette question . La différence de pointeur est exprimée en éléments et non en octets.

7
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)

Cette macro my_sizeof() ne fonctionnera pas dans les cas suivants:

  1. sizeof 1 - 4 octets (pour une plate-forme avec 4 octets int)
    my_sizeof(1) - ne compilera pas du tout.

  2. sizeof (int) - 4 octets (pour une plate-forme avec 4 octets int)
    my_sizeof(int) - ne compilera pas le code du tout.

Cela fonctionnera seulement pour les variables. Cela ne fonctionnera pas pour les types de données comme int, float, char etc., pour les littéraux tels que 2, 3.4, 'A', etc., ni pour les expressions rvalue telles que a+b ou foo().

6
Kuppappa DH

Mais il finissait toujours par donner le résultat «1» pour l'un ou l'autre type de données

Oui, c'est comme ça que l'arithmétique de pointeur fonctionne. Cela fonctionne dans les unités du type indiqué. Donc, transtyper char * fonctionne comme un ensemble de char, ce que vous voulez.

5
#define my_sizeof(x) ((&x + 1) - &x)

&x donne l'adresse de la variable (disons double x) déclarée dans le programme et l'incrémente de 1 donne l'adresse où la variable suivante de type x peut être stockée (ici addr_of(x) + 8, la taille d'un double étant de 8 octets).

La différence donne comme résultat que combien de variables de type x peuvent être stockées dans cette quantité de mémoire qui sera évidemment 1 pour le type x (pour l'incrémenter avec 1 et prendre la différence, c'est ce que nous avons fait). 

#define my_size(x) ((char *)(&x + 1) - (char *)&x)

le transtyper en char* et prendre la différence nous dira combien de variables de type char peuvent être stockées dans l'espace mémoire donné (la différence). Puisque chaque char nécessite seulement 1 octet de mémoire, donc (quantité de mémoire)/1 donnera le nombre d'octets entre deux emplacements mémoire successifs du type de variable transmise à la macro et donc la quantité de mémoire que la variable de type x a besoin.

Mais vous ne pourrez passer aucun littéral à cette macro et connaître leur taille.

5
roottraveller

J'ai cherché cela hier et j'ai trouvé cette macro:

#define mysizeof(X)  ((X*)0+1)

Ce qui étend X une seule fois (pas d’erreur comme double évaluation d’expression comme x ++), et ça marche jusqu’à présent.

0
C.Y