clarificación de matriz sizeof

Estoy estudiando para una final mañana en C, y tengo una pregunta sobre el tamaño del operador.

Digamos que el tamaño de un int es de 32 bits y un puntero es de 64 bits.

Si hubiera una función:

 int foo (int zap[]) { int a = sizeof(zap); return a; } 

Debido a que zap es un puntero, foo devolvería 8 , ya que esa es la cantidad de bytes necesarios para almacenar este puntero en particular. Sin embargo, con el siguiente código:

 int zip[] = { 0, 1, 2, 3, 4, 5 }; int i = sizeof(zip); 

i sería 6 * sizeof(int) = 6 * 4 = 24

¿Por qué es que sizeof(zip) devuelve el número de elementos multiplicado por el tamaño de cada elemento, mientras que sizeof(zap) devuelve el tamaño de un puntero? ¿Es que el tamaño de zap no está especificado, y zip no? El comstackdor sabe que zip tiene 6 elementos, pero no tiene ni idea de qué tan grande puede ser el zap .

Esto es una especie de asimetría en la syntax C. En C, no es posible pasar una matriz a una función, por lo que cuando se usa la syntax de la matriz en una statement de función para uno de los parámetros, el comstackdor la lee como un puntero.

En C, en la mayoría de los casos, cuando usa una matriz en una expresión, la matriz se convierte implícitamente en un puntero a su primer elemento y eso es exactamente lo que sucede, por ejemplo, cuando llama a una función. En el siguiente código:

 int bar[] = {1,2,3,4}; foo(bar); 

la matriz se convierte en un puntero al primer elemento y eso es lo que recibe la función.

Sin embargo, esta regla de conversión implícita no siempre se aplica. Como descubrió, por ejemplo, el operador sizeof trabaja en la matriz, e incluso el operador & (address-of) trabaja en la matriz original (es decir, sizeof(*&bar) == 4*sizeof(int) ).

Una función en C no puede recibir una matriz como parámetro, solo puede recibir un puntero al primer elemento, o un puntero a una matriz … o debe envolver la matriz en una estructura.

Incluso si pones un número entre los paréntesis en la statement de función …

 void foo(int x[4]) { ... } 

ese número es completamente ignorado por el comstackdor … esa statement para el comstackdor es totalmente equivalente a

 void foo(int *x) { ... } 

y, por ejemplo, incluso llamarlo pasando una matriz con un tamaño diferente no generará ningún error …

 int tooshort[] = {1,2,3}; foo(tooshort); /* Legal, even if probably wrong */ 

(en realidad, un comstackdor PUEDE dar una advertencia, pero el código es perfectamente legal C y debe aceptarse si el comstackdor sigue el estándar)

Si piensa que esta regla sobre matrices cuando está en argumentos de función es extraña, entonces estoy de acuerdo, pero así es como se define el lenguaje C.

Porque zip es una matriz y el comstackdor conoce su tamaño en tiempo de comstackción . Es solo un caso de usar la misma notación para dos cosas diferentes, algo bastante habitual en C.

 int foo (int zap[]) 

es completamente equivalente a

 int foo (int *zap) 

El comstackdor no tiene idea de cuán grande podría ser zap (por lo que deja la tarea de averiguarlo al progtwigdor).

zip es un bloque de memoria de 6 * sizeof(int) por lo que tiene un tamaño de 24 (en su architecture). zap (también podría escribirse como int *zap en su statement de función) sin embargo, puede apuntar a cualquier dirección de memoria y el comstackdor no tiene forma de saber cuánto espacio comienza en esta dirección (o incluso que la contiene) ha sido asignado.

El tamaño de zip es conocido en el momento de la comstackción y el tamaño de zap no. Es por eso que está obteniendo el tamaño de un puntero en sizeof(zap) y el tamaño de la matriz en sizeof(zip) .

Hay algunas situaciones en las que los arreglos decaen a los punteros. Llamadas de función es uno de esos.

Porque se ha inicializado estáticamente con 6 elementos.