2010-06-22 18 views
10

Conozco C++ y conozco la función sizeof, pero necesito escribir mi propio tamaño de función así que explique cómo funciona exactamente. ¿Qué hace con el parámetro?¿Cómo funciona sizeof? ¿Cómo puedo escribir el mío?

+17

'sizeof' no es una función, es un operador especial que asigna tipos a enteros en tiempo de compilación. – fredoverflow

+0

ok y cómo implementarlo por función de manera que haga el mismo trabajo que sizeof? –

+8

@davit la respuesta es usted * no puede *, al menos no sin hacer uso del 'sizeof' existente. No es algo que se pueda hacer en tiempo de ejecución. –

Respuesta

25

No ha proporcionado ningún detalle significativo sobre lo que quiere hacer, por lo que es difícil averiguar lo que necesita.

se puede "envolver" sizeof por usted propia función de plantilla como

template <typename T> size_t my_sizeof() { 
    return sizeof(T); 
} 

y luego usarlo como

size_t s = my_sizeof<int>(); 

De vez en cuando uno puede venir a través de una solicitud para implementar sizeof parecido funcionalidad sin usando sizeof. Solicitudes como esa no tienen ningún sentido práctico en absoluto, pero a veces se usan como tareas para el hogar. Probablemente uno puede hacerlo de la siguiente manera

template <typename T> size_t my_sizeof() { 
    T t; 
    return (char *) (&t + 1) - (char *) &t; 
} 

que requeriría un defecto Urbanizable T. Una solución menos restrictiva pero formalmente ilegal (un corte) sería algo así como

template <typename T> size_t my_sizeof() { 
    return (char *) ((T *) NULL + 1) - (char *) (T *) NULL; 
} 

Las implementaciones anteriores implementan sizeof basado en el tipo.

un intento de emular la funcionalidad de sizeof podría ser el siguiente

template <typename T> size_t my_sizeof(const T& obj) { 
    return my_sizeof<T>(); 
} 

pero esto no será ni remotamente equivalente al valor basado en la incorporada en sizeof, si por lo menos, porque la incorporada en sizeof no evalúa su argumento

Por último, ninguna de estas implementaciones generará expresiones constantes integrales (ICE), como lo hace el sizeof incorporado. Producir un ICE de esa manera es imposible de lograr en la versión actual del idioma.

En cualquier caso, todo esto, por supuesto, está totalmente desprovisto de valor práctico. Simplemente use sizeof cuando quiera saber el tamaño.

+2

asignación de tarea bastante estúpida para envolver sizeof() si me preguntas –

+0

Pensé en el char * piratear también. Un ejercicio tonto de hecho. – Reinderien

+1

Por supuesto, el hecho de que esto funcione depende completamente del invariante en tiempo de compilación 'sizeof (char) == 1', que es un poco catch-22. –

31

sizeof es un compilador de operador incorporado. El compilador lo evalúa en tiempo de compilación y no hay código de tiempo de ejecución detrás de él. No puedes escribir el tuyo

Preguntar esto es similar a preguntar cómo escribirías tu propia versión de return.

+0

Puede, sin embargo, crear un * wrapper * para 'sizeof', que podría ser lo que necesita el OP. Difícil de decir sin más contexto. –

+0

ok gracias, entiendo –

+0

Su confusión es comprensible, ya que * puede * anular nueva/eliminar. –

1

sizeof no es una función, y no puede escribir su propia versión. El compilador resuelve el tipo del argumento (a menos que ya sea un tipo), luego sustituye la expresión con una constante entera.

4

Como ya se ha dicho, no es un operador de una función, pero, además, es uno de los operadores para los que no se permite la sobrecarga de operadores:

Bjarne Stroustrup's C++ Style and Technique FAQ: Why can't I overload dot, ::, sizeof, etc.?

puedo pensar en ninguna razón concebible por las que se quiero sobrecargar esto en cualquier caso.Si tiene una clase para la que se requiere información de tamaño diferente a la que se requiere sizeof, simplemente agregue una función miembro para proporcionar esa información; como por ejemplo en std::string:size() que devuelve la longitud de la cadena administrada por el objeto en lugar del tamaño del objeto que es semánticamente diferente; usted no quiere moniar con la semántica de sizeof!

0

Si quiere escribir su propio tamaño, solo tiene que tomar el código fuente de un compilador C++ y seguir adelante. La fuente también mostrará cómo se puede implementar sizeof.

+0

Probablemente se implementaría utilizando estructuras de datos internas del compilador a las que no se podría acceder a través de la fuente C++. –

+0

Me has malentendido. Mi consejo fue crear un compilador modificado a partir de una fuente de compilación existente. Esto puede ser muy educativo. –

7

Una forma no portátil para escribir su propia sizeof() es aprovecharse de cómo las variables basado en pilas se colocan a menudo en la memoria:

#include <iostream> 
using namespace std; 

template <typename T> 
int mysizeof(T) 
{ 
    T temp1; 
    T temp2; 

    return (int)&temp1 - (int)&temp2; 
} 

int main() 
{ 
    cout << "sizeof mysizeof" << endl; 

    char c = 0; short s = 0; int i = 0; long l = 0; 
    float f = 0; double d = 0; long double ld = 0; 

    cout << "char: " << mysizeof(c) << endl; 
    cout << "short: " << mysizeof(s) << endl; 
    cout << "int: " << mysizeof(i) << endl; 
    cout << "long: " << mysizeof(l) << endl; 
    cout << "float: " << mysizeof(f) << endl; 
    cout << "double: " << mysizeof(d) << endl; 
    cout << "long double: " << mysizeof(ld) << endl; 
} 

See it in action.
A 0-parameter version.
A version that uses one array instead of two variables.

Advertencia: este fue un rompecabezas divertido, pero nunca debes usar esto en código real. sizeof está garantizado para funcionar. Esto no es. El hecho de que funcione en esta versión de este compilador para esta plataforma no significa que funcionará para ningún otro.

El operador real se aprovecha de ser parte del compilador. Sizeof sabe qué tan grande es cada tipo de variable porque tiene que saber. Si el compilador no sabe qué tan grande es cada tipo, no podría colocar su programa en la memoria.

Edición: Tenga en cuenta que todos estos ejemplos defectuosos se basan en el operador original sizeof. Se usa para espaciar las variables de pila y para crear e indexar variables de matriz.

+4

Probablemente sería más seguro tener una matriz de dos elementos, en lugar de contar con el compilador para ubicar a los locales en un orden determinado. array [1] siempre viene después de la matriz [0], y con el relleno adecuado. –

+0

@dash: pensé en eso también, pero me distraí. Actualicé mi respuesta con un enlace a una implementación basada en arreglos. – Bill

+1

Ninguna implementación funciona en una clase abstracta o una clase que carece de un constructor público de parámetro cero tampoco. – jmucchiello

0

sizeof se evalúa en tiempo de compilación (Boost y Loki lo utilizan). Entonces, creo, es imposible escribir sizeof - función de queja para el búfer asignado dinámicamente.

2

sizeof es un operador de C++ que produce el número de bytes en la representación del objeto de su operando. El resultado de sizeof es una constante definida por la implementación del tipo size_t, pero debe cumplir los requisitos establecidos en el estándar 5.3.3 de C++. Puede escribir sus propios rasgos de tipo que funcionen de forma similar al operador sizeof incorporado.

template<typename T> struct get_sizeof; 

template<> struct get_sizeof<char>   { static const size_t value = 1; }; 
template<> struct get_sizeof<unsigned char> { static const size_t value = 1; }; 
template<> struct get_sizeof<int>   { static const size_t value = 4; }; 
template<> struct get_sizeof<long>   { static const size_t value = 4; }; 
// etc. 

... 
// sample of use 
static const size_t size = get_sizeof<int>::value; 
char x[get_sizeof<int>::value]; 

Pero esto no tiene sentido, ya que sólo los creadores del compilador están sabe valores reales de value para la aplicación.

0

sizeof no es una función. Es un operador en C. Podemos implementar su funcionalidad de la siguiente manera.

#include <stdio.h> 

#define mysizeof(X) \ 

      ({     \ 
        __typeof(X) x; \ 
        (char *) (&x+1) - (char*) (&x); \ 
      }) 
int main() 
{ 

    struct sample 
    { 
     int a;float b; char c; 
    }; 

    printf("%d", mysizeof(struct sample)); 
    return 0; 
} 

respuesta: 12

1

vi este post en la búsqueda de una manera de conseguir la misma funcionalidad que el operador sizeof. Resultó que implementé una función llamada bit_sizeof() que se parece mucho al operador sizeof, pero que en su lugar devuelve el número de bits de un tipo determinado. He implementado una función plantilla global de esta manera:

#include <limits.h> //For CHAR_BIT 

//Global function bit_sizeof() 
template<typename TSizeOfType> 
constexpr uint32_t bit_sizeof(TSizeOfType) 
{ 
    return (sizeof(TSizeOfType) * CHAR_BIT); 
} 

Esta función requiere el uso de la C++ 11 estándar, ya que utiliza la palabra clave constexpr.Sin la palabra clave constexpr, la función compilará aún. Sin embargo, es posible que el compilador no se optimice correctamente y realice una llamada a función en cada sitio de llamada utilizando la función bit_sizeof. Con el uso de constexpr, toda la función se evalúa como una constante, que en mi conocimiento debería ser exactamente equivalente a cómo funciona el tamaño del operador. Corrígeme si estoy equivocado. En el uso que llamo la función como esta, con un parantesis añadido después del tipo:

uint32_t uiBitsInType = bit_sizeof(char()); 

La función puede ser útil para crear máscaras de bits, por ejemplo:

uint32_t uiMask = (((uint32_t(0x1) << bit_sizeof(char())) - 0x1) << bit_sizeof(char())); 

que podría ser más fácil de leer que este :

uint32_t uiMask2 = (((uint32_t(0x1) << (sizeof(char) * 0x8)) - 0x1) << (sizeof(char) * 0x8)); 

Personalmente tengo otros usos para esta función también.

+0

Es posible que desee comprobar 'CHAR_BIT'. Además, '_T' es un prefijo reservado para los nombres definidos por la implementación. Solo suelta el '_', las plantillas C++ no son macros. Obedecen el alcance, por lo que 'typename TSizeOfType' es visible solo dentro de la plantilla. – MSalters

+0

Oh, gracias. Hice los cambios como sugirió. – Peter

Cuestiones relacionadas