sintaxis array c sizeof

c - array - sizeof string



¿Por qué sizeof(x++) no incrementa x? (8)

Aquí está el código compilado en dev c ++ windows:

#include <stdio.h> int main() { int x = 5; printf("%d and ", sizeof(x++)); // note 1 printf("%d/n", x); // note 2 return 0; }

Espero que x sea ​​6 después de ejecutar la nota 1 . Sin embargo, la salida es:

4 and 5

¿Alguien puede explicar por qué x no aumenta después de la nota 1 ?


Como el operando de sizeof operator no se evalúa, puede hacer esto:

int f(); //no definition, which means we cannot call it int main(void) { printf("%d", sizeof(f()) ); //no linker error return 0; }

Demostración en línea: http://ideone.com/S8e2Y

Es decir, no es necesario definir la función f si se usa solo en sizeof . Esta técnica se utiliza principalmente en la metaprogramación de plantillas de C ++, ya que incluso en C ++, el operando de sizeof no se evalúa.

¿Por qué funciona esto? Funciona porque el operador sizeof no opera con el valor , sino que opera con el tipo de expresión. Entonces, cuando escribe sizeof(f()) , opera en el tipo de expresión f() , y que no es más que el tipo de retorno de la función f . El tipo de retorno siempre es el mismo, independientemente del valor que devolvería la función si se ejecuta realmente.

En C ++, puedes incluso esto:

struct A { A(); //no definition, which means we cannot create instance! int f(); //no definition, which means we cannot call it }; int main() { std::cout << sizeof(A().f())<< std::endl; return 0; }

Sin embargo, parece que, en sizeof , primero estoy creando una instancia de A , escribiendo A() , y luego llamando a la función f en la instancia, escribiendo A().f() , pero no sucede nada de eso.

Demostración: http://ideone.com/egPMi

Aquí hay otro tema que explica algunas otras propiedades interesantes de sizeof :


Desde el Estándar C99 (el énfasis es mío)

6.5.3.4/2

El operador sizeof produce el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo. El tamaño se determina a partir del tipo de operando. El resultado es un entero. Si el tipo del operando es un tipo de matriz de longitud variable, se evalúa el operando; de lo contrario, el operando no se evalúa y el resultado es una constante entera.


La ejecución no puede ocurrir durante la compilación. Así que ++i / i++ no sucederá. Además, sizeof(foo()) no ejecutará la función pero devolverá el tipo correcto.


Nota

Esta respuesta se combinó de un duplicado, lo que explica la fecha tardía.

Original

A excepción de las matrices de longitud variable, sizeof no evalúa sus argumentos. Podemos ver esto en la sección 6.5.3.4 del borrador de la norma C99. El tamaño del párrafo 2 del operador, que dice:

El operador sizeof produce el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo. El tamaño se determina a partir del tipo de operando. El resultado es un entero. Si el tipo del operando es un tipo de matriz de longitud variable, se evalúa el operando; de lo contrario, el operando no se evalúa y el resultado es una constante entera.

Un comentario ( ahora eliminado ) preguntó si algo como esto se evaluaría en tiempo de ejecución:

sizeof( char[x++] ) ;

y de hecho lo haría, algo como esto también funcionaría ( Véalos en vivo ):

sizeof( char[func()] ) ;

ya que ambos son arrays de longitud variable. Aunque, no veo mucho uso práctico en ninguno de los dos.

Tenga en cuenta que los arreglos de longitud variable están cubiertos en el borrador de la sección 6.7.5.2 norma C99 , párrafo 4 de los 6.7.5.2 arreglos :

[...] Si el tamaño es una expresión constante de entero y el tipo de elemento tiene un tamaño constante conocido, el tipo de matriz no es un tipo de matriz de longitud variable; de lo contrario, el tipo de matriz es un tipo de matriz de longitud variable.

Actualizar

En C11, la respuesta cambia para el caso VLA, en algunos casos no se especifica si la expresión de tamaño se evalúa o no. De la sección 6.7.6.2 que dice:

[...] Cuando una expresión de tamaño es parte del operando de un operador sizeof y cambiar el valor de la expresión de tamaño no afectaría el resultado del operador, no se especifica si la expresión de tamaño se evalúa o no.

Por ejemplo, en un caso como este ( verlo en vivo ):

sizeof( int (*)[x++] )


sizeof() operador sizeof() da el tamaño del tipo de datos solamente, no evalúa los elementos internos.


sizeof(foo) intenta realmente descubrir el tamaño de una expresión en tiempo de compilación:

6.5.3.4:

El operador sizeof produce el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo. El tamaño se determina a partir del tipo de operando. El resultado es un entero. Si el tipo del operando es un tipo de matriz de longitud variable, se evalúa el operando; de lo contrario, el operando no se evalúa y el resultado es una constante entera.

En resumen: arrays de longitud variable, ejecutados en tiempo de ejecución. (Nota: las matrices de longitud variable son una característica específica, no las matrices asignadas con malloc(3) . De lo contrario, solo se calcula el tipo de expresión, y eso en el momento de la compilación.


sizeof es un operador en tiempo de compilación, por lo que en el momento de la compilación sizeof y su operando son reemplazados por el valor del resultado. El operando no se evalúa (excepto cuando es una matriz de longitud variable); sólo importa el tipo de resultado.

short func(short x) { // this function never gets called !! printf("%d", x); // this print never happens return x; } int main() { printf("%d", sizeof(func(3))); // all that matters to sizeof is the // return type of the function. return 0; }

Salida:

2

Tan short ocupa 2 bytes en mi máquina.

Cambiando el tipo de retorno de la función a double :

double func(short x) { // rest all same

Dará 8 como salida.


sizeof es un operador incorporado en tiempo de compilación y no es una función. Esto queda muy claro en los casos en que puede usarlo sin el paréntesis:

(sizeof x) //this also works