2010-08-26 12 views
25

Esto puede ser una pregunta estúpida, pero ¿cómo sabe el operador de sizeof el tamaño de un operando de matriz cuando no se pasa la cantidad de elementos en la matriz. Sé que no devuelve el total de elementos en la matriz, pero el tamaño en bytes, pero para obtenerlo, todavía tiene que saber cuándo termina la matriz. Solo curiosidad sobre cómo funciona esto.¿Cómo sabe sizeof el tamaño de la matriz de operandos?

+0

Ver: 1 http://stackoverflow.com/questions/492384/how-to-find-the-sizeof-a-pointer-pointing-to-an-array –

+6

a todos los que decían ' sizeof' era un operador de tiempo de compilación, -1 para todos los que dijeron que rastreó el tamaño de la matriz a la que apunta un puntero en tiempo de ejecución. –

+0

¡Guau! diez respuestas hasta que terminé mi respuesta. Me estoy haciendo viejo ;-) – stacker

Respuesta

39

se interpreta en tiempo de compilación, y el compilador sabe cómo se declaró la matriz (y, por tanto, cuánto espacio ocupa). Llamar al sizeof en una matriz asignada dinámicamente probablemente no hará lo que usted desea, porque (como usted menciona) el punto final de la matriz no está especificado.

+0

bastante seguro de que esto no es cierto, según la discusión sobre la pregunta en sí misma, así como leyendo la especificación, al menos para la versión moderna de C. Sería mejor eliminar esta respuesta. http: //en.wikipedia.org/wiki/Sizeof – xaxxon

+2

@xaxxon: el estándar no * explícitamente * dice que se evalúa en tiempo de compilación, pero sí dice que 'sizeof' no evalúa su operando. La expresión de operando solo tiene sentido para el compilador, por lo que es realmente el único lugar donde puede implementarse. Los VLA son manejados indirectamente por el compilador. El compilador ya debe generar código para calcular cuánto espacio asignar para el VLA (el tamaño del miembro de la matriz * alguna variable), por lo que puede reutilizar ese número para cualquier llamada 'sizeof' en ese VLA. – bta

9

El compilador conoce el tamaño de cada tipo en su aplicación, y sizeof solo solicita al compilador que produzca ese valor para usted.

+0

Esto no es verdad. el tamaño de la matriz de longitud variable de las llamadas no se maneja en tiempo de compilación. Debes actualizar tu respuesta o eliminarla. http://en.wikipedia.org/wiki/Sizeof – xaxxon

+0

@xaxxon: A partir de ahora, las matrices de longitud variable no son válidas en C++, por lo que la respuesta es válida: el tamaño de * todos los tipos válidos de C++ * se calcula en tiempo de compilación. Los arreglos de longitud variable para C++ se propusieron al comité en la última reunión, y la propuesta fue bien recibida, pero eso no será válido en C++ hasta que se apruebe el siguiente estándar (C++ 14). Incluso con los VLA, el compilador * conoce * el tamaño (conoce la expresión a partir de la cual se creó el conjunto, por lo que puede guardar el número), dado que los VLA no pueden escaparse del alcance de la función, el compilador puede inyectar el mismo valor donde es necesario. –

8

Sizeof es un operador de tiempo de compilación; tiene tanta información como el compilador. (Y obviamente el compilador sabe el tamaño de la matriz).

Esta es la razón por la que si llama al sizeof en un puntero obtendrá el ancho del puntero, no el tamaño de la matriz apuntada por ese puntero.

+0

Entonces, (sin haber usado C++ durante algunos años), ¿qué ocurre si solicita un tamaño y una desreferencia del puntero a la matriz? ¿Sizeof simplemente falla, o busca algo que haya registrado sobre el tamaño de la matriz y lo devuelve? –

+2

Si desreferencia el puntero, obtendrá una referencia al objeto almacenado en la matriz, y sizeof lo devolverá. 'int a [5]; int * p = a; assert (sizeof (* p) == sizeof (int); ' –

+0

Esto no es cierto. El tamaño de la matriz de longitud variable de las llamadas no se maneja en tiempo de compilación. Debe actualizar su respuesta o eliminarla. http: //en.wikipedia. org/wiki/Sizeof – xaxxon

2

Si está usando sizeof en una variable local, sabe cuántos elementos ha declarado. Si está utilizando sizeof en un parámetro de función, no lo sabe; trata el parámetro como un puntero a la matriz y sizeof da el tamaño de un puntero.

+0

Lo hace saber. El parámetro * es * un puntero (al primer elemento, no a la matriz) y el compilador conoce el tamaño del puntero. C no tiene parámetros de matriz. –

12

Excepto en un caso, sizeof lo hace en tiempo de compilación. En tiempo de compilación, el compilador realiza un seguimiento del tipo completo de un objeto [Editar: bueno, todo lo que sabe sobre el tipo del objeto, de todos modos - si el tipo no está completo, por lo que no incluye el tamaño , intentar usar sizeof fallará], y sizeof básicamente solo "exporta" una parte de esa información del compilador al código que se está compilando, por lo que se convierte esencialmente en una constante en el código resultante.

La excepción es cuando se aplica sizeof a la matriz de longitud variable (VLA) . Cuando se aplica a un VLA, sizeof evalúa su operando (que de otro modo no lo hace) y produce el tamaño real del VLA. En este caso, el resultado no es una constante.


1. VLA se convirtió oficialmente en una parte de C en el C99, pero algunos compiladores los apoyó antes de eso. Aunque oficialmente no forma parte de C++, algunos compiladores (por ejemplo, g ++) incluyen VLA como una extensión de C++ también.

+3

El compilador realiza un seguimiento del tipo completo ... a menos que no lo haga porque el tipo está incompleto. En ese caso, 'sizeof' no se puede usar. – Potatoswatter

+0

@Potatoswatter: buen punto. Modificado para reflejar ese hecho. –

+0

Esto no es verdad. el tamaño de la matriz de longitud variable de las llamadas no se maneja en tiempo de compilación. Debes actualizar tu respuesta o eliminarla. http://en.wikipedia.org/wiki/Sizeof – xaxxon

1

Presupuesto de wiki:

Es responsabilidad del autor del del compilador para poner en práctica el operador sizeof de una manera específica y correcto para una aplicación dada de el idioma. El operador sizeof debe tener en cuenta la implementación del esquema de asignación de memoria subyacente para obtener los tamaños de varios tipos de datos.sizeof es , generalmente un operador en tiempo de compilación, que significa que durante la compilación, el tamaño de y su operando son reemplazados por el resultado-valor . Esto es evidente en el código de lenguaje ensamblador producido por un compilador C o C++. Por esta razón, sizeof califica como operador, incluso aunque su uso a veces se parece a una llamada de función .

+2

Si bien esto es cierto, realmente no responde la pregunta del OP. –

1

El sizeof operator 'sabe' el tamaño de todos los tipos de datos atómicos, desde estructuras, los sindicatos y las matrices sólo pueden ser construidos mediante el ensamblaje de los tipos atómicos es fácil determinar el tamaño de la matriz de cualquier tipo. Utiliza aritmética básica para determinar tipos complejos (durante el tiempo de compilación).

4

Sizeof solo se puede aplicar a tipos completamente definidos. El compilador podrá determinar el tamaño en tiempo de compilación (por ejemplo, si tiene una declaración como int foo [8];), o podrá determinar que tiene que agregar código para rastrear el tamaño de una variable -length array (por ejemplo, si tiene una declaración como int foo [n + 3];).

Contrariamente a otras respuestas aquí, tenga en cuenta que a partir de C99, sizeof() es no necesariamente determinado en tiempo de compilación, ya que las matrices pueden ser de longitud variable.

+0

s/runtime/compile time/g y se convierte en una buena respuesta. – ninjalj

+0

Derp. Gracias. :-) – ngroot

+0

Hable acerca de las profecías autocumplidas :) – ninjalj

19

El problema subyacente de su problema para comprender esto podría deberse a que está confundiendo matrices e indicadores, como hacen muchos. Sin embargo, matrices no son punteros. Un double da[10] es una matriz de diez double, no un double*, y eso es ciertamente conocido por el compilador cuando lo solicite evaluar sizeof(da). ¿No le sorprendería que el compilador conozca sizeof(double)?

El problema con las matrices es que decaen a punteros a sus primeros elementos automáticamente en muchos contextos (como cuando se pasan a las funciones). Pero aún así, array son matrices y los punteros son punteros.

+2

+1 para explicar la raíz del malentendido común aquí. –

+0

Absolutamente correcto, sbi. Los capítulos 4, 9 y 10 del excelente libro "Expert C Programming" de Peter van der Linden hacen un gran trabajo al hacer la distinción entre punteros y matrices. Demonios, el Capítulo 4 se titula "La impactante verdad: las matrices C y los indicadores no son lo mismo", como dijo sbi. Y dedica 15 páginas al tema. Consulte la tabla de contenido, esp. Ch. 4, 9 y 10: http://books.google.com/books?id=9t5uxP9xHpwC&lpg=PP1&dq=expert%20c%20programming&pg=PR8#v=onepage&q&f=false – Dan

0

sizeof se calcula en tiempo de compilación. Por esta razón, cuando crea una matriz dinámica, la crea de la siguiente manera.

char * array; 
int size; 
//Get size somehow. 
array = malloc(size*(sizeof(char))); 

// ahora durante la compilación, el compilador sabe con certeza el tamaño de char. ya que tiene que alinearlos en la memoria. En este punto, el sistema operativo sabe cuánto tamaño tiene que asignar.

matrices de longitud variable por otro lado se crean en el Pila. Pero cualquier memoria malloc asignada se crearía en el montón.

0

Sizeof siempre se evalúa en tiempo de compilación. En el compilador de pasadas múltiples mientras se genera el compilador de la tabla de símbolos, se debe determinar el tamaño de cada símbolo declarado para avanzar y generar un código intermedio. Entonces, para todos los tamaños de referencias en el código, se reemplaza el valor exacto. En la etapa de generación de código intermedio todos los operadores, las declaraciones se convierten en código intermedio derecho (ASM/otro formato). Finalmente, la etapa de generación de código m/c lo convierte en el código de máquina.

Algunas discusiones vistas arriba w.r.t las asignaciones dinámicas relacionadas con sizeof no están en el contexto en absoluto. Cualquier referencia al tamaño (* p) donde p es un puntero de cualquier tipo de datos, el compilador simplemente descubre el tipo de datos de * p y reemplaza su tamaño, no va a verificar el encabezado MCB del bloque asignado para ver qué se le asigna tamaño de la memoria. No está en tiempo de ejecución.Por ejemplo, double * p; sizeof (* p) aún se puede hacer sin asignar memoria para el puntero p. ¿Como es posible?

+0

"Sizeof siempre se evalúa en tiempo de compilación". Esto no es cierto para las matrices de longitud variable, como se discutió en otras respuestas y comentarios de preguntas. Esta respuesta debe eliminarse y es incorrecta para el lenguaje C actual (lea la especificación). http://en.wikipedia.org/wiki/Sizeof – xaxxon

1

sizeof es generalmente evaluado en tiempo de compilación. La notable excepción son las matrices de longitud variable de C99.

int main(int argc, char **argv) 
{ 
    if (argc > 1) 
    { 
     int count = atoi(argv[1]); 
     int someArray[count]; 

     printf("The size is %zu bytes\n", sizeof someArray); 
    } 
    else puts("No"); 
} 
Cuestiones relacionadas