
Raghu Srikanth Reddy
He intentado implementar el operador sizeof. lo he hecho de esta forma:
#define my_sizeof(x) ((&x + 1) - &x)
Pero siempre terminaba dando el resultado como ‘1’ para cualquiera de los tipos de datos.
Luego lo busqué en Google y encontré el siguiente código:
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
Y el código está funcionando si es encasillado, no entiendo por qué. Este código también está ACOLCHANDO una ESTRUCTURA perfectamente.
También está trabajando para:
#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)
¿Alguien puede explicar cómo funciona si está encasillado?
El resultado de la resta del puntero está en elementos y no en bytes. Así, la primera expresión se evalúa como 1
por definición.
Aparte de esto, deberías usar paréntesis en las macros:
#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
De lo contrario, intentar usar my_sizeof()
en una expresión puede dar lugar a errores.

Basile Starynkevitch
los sizeof
El operador es parte de la especificación del lenguaje C (y C++) y se implementa dentro del compilador (el front-end). No hay forma de implementarlo con otras construcciones C (a menos que use extensiones GCC como tipo de) porque puede aceptar tipos o expresiones como operandos, sin tener ningún efecto secundario (p. ej. sizeof((i>1)?i:(1/i))
no se estrellará cuando i==0
pero tu macro my_sizeof
chocaría con una división por cero). Ver también Directrices de codificación Cy wikipedia.
deberías entender c aritmética de punteros. Véase, por ejemplo, esta pregunta. La diferencia de puntero se expresa en elementos, no en bytes.

Kuppappa DH
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
Esta my_sizeof()
macro no funcionará en los siguientes casos:
-
sizeof 1
– 4 bytes (para una plataforma con 4 bytes int
)
my_sizeof(1)
– no compilará en absoluto.
-
sizeof (int)
– 4 bytes (para una plataforma con 4 bytes int
)
my_sizeof(int)
– no compilará código en absoluto.
Funcionará solo para variables. No funcionará para tipos de datos como int
, float
, char
etc., para literales como 2
, 3.4
, 'A'
etc., ni para expresiones rvalue como a+b
o foo()
.
#define my_sizeof(x) ((&x + 1) - &x)
&x
da la dirección de la variable (digamos doble x) declarada en el programa e incrementándola en 1 da la dirección donde se puede almacenar la siguiente variable del tipo x (aquí addr_of(x) + 8
porque el tamaño de un doble es 8Byte).
La diferencia da como resultado que cuantas variables de tipo de x
se puede almacenar en esa cantidad de memoria que obviamente será 1 para el tipo x (porque incrementarlo en 1 y sacar la diferencia es lo que hemos hecho).
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
encasillándolo en char*
y sacando la diferencia nos dirá cuantas variables de tipo char
se puede almacenar en el espacio de memoria dado (la diferencia). Desde cada uno char
requiere solo 1 byte de memoria, por lo tanto (cantidad de memoria)/1 dará la cantidad de bytes entre dos ubicaciones de memoria sucesivas del tipo de variable pasada a la macro y, por lo tanto, la cantidad de memoria que la variable de tipo x
requiere
Pero no podrá pasar ningún literal a esta macro y conocer su tamaño.
Pero siempre terminaba dando el resultado como ‘1’ para cualquiera de los tipos de datos
Sí, así es como funciona la aritmética de punteros. Funciona en unidades del tipo al que se apunta. Así que lanzando a char *
unidades de trabajo de char
que es lo que quieres.

SakthiKarthik
Esto funcionará tanto para literales como para variables.
#define my_sizeof(x) (char*) (&(((__typeof__(x) *)0)[1])) - (char *)(&(((__typeof__(x) *)0)[0]))

CY
Busqué esto ayer, y encontré esta macro:
#define mysizeof(X) ((X*)0+1)
Que expande X solo una vez (sin error como doble evaluación de expresión como x ++), y funciona bien hasta ahora.
Casting a
unsigned int
es una mala ideauintptr_t
es mejor pero aún implica una conversión implícita molesta pero inevitable.– Pascal Cuoq
5 de enero de 2013 a las 11:12
tu básicamente no poder implementar
sizeof
. Es una parte esencial del lenguaje C.– Basile Starynkevitch
2 de abril de 2019 a las 7:24