Advertencia de inicialización de tipo de puntero incompatible al asignar a un puntero

Advertencia de inicialización de tipo de puntero incompatible al asignar a un puntero


GCC me da una advertencia de 'Inicialización del tipo de puntero incompatible' cuando uso este código (aunque el código funciona bien y hace lo que se supone que debe hacer, que es imprimir todos los elementos de la matriz).


#include <stdio.h>
int main(void)
{
int arr[5] = {3, 0, 3, 4, 1};
int *p = &arr;
printf("%p\n%p\n\n", p);
for (int a = 0; a < 5; a++)
printf("%d ", *(p++));
printf("\n");
}

Sin embargo, no se da ninguna advertencia cuando uso este fragmento de código


int main(void)
{
int arr[5] = {3, 0, 3, 4, 1};
int *q = arr;
printf("%p\n%p\n\n", q);
for (int a = 0; a < 5; a++)
printf("%d ", *(q++));
printf("\n");
}

La única diferencia entre estos dos fragmentos es que asigno *p =&arr y *q =arr .



  • ¿Exactamente qué diferente es el &haciendo?

  • ¿Y por qué el código se ejecuta y da exactamente el mismo resultado en ambos casos?


Respuestas:



  • &arr da un puntero de matriz , un tipo de puntero especial int(*)[5] que apunta a la matriz como un todo.

  • arr , cuando se escribe en una expresión como int *q = arr; , "decae" en un puntero al primer elemento. Totalmente equivalente a int *q = &arr[0];


En el primer caso, intenta asignar un int(*)[5] a un int* . Estos son tipos de punteros incompatibles, de ahí el mensaje de diagnóstico del compilador.


Resulta que el puntero de matriz y el puntero int al primer elemento muy probablemente tendrán la misma representación y la misma dirección internamente. Por eso el primer ejemplo "funciona" aunque no sea correcto C.