Parece que no tienes del todo claro cómo funcionan los operadores unarios1 *
(des-referencia) y &
(dirección de).
Contexto.
El operador de "des-referencia" o "contenido-de" sólo puede ser usado con punteros (o al declarar punteros) y obtiene el contenido de lo que sea que apunta el puntero:
int valor = 42;
int* puntero = &valor;
int** puntero_a_puntero = &puntero;
int*** puntero_a_puntero_a_puntero = &puntero_a_puntero;
printf("%d", ***puntero_a_puntero_a_puntero); // Muestra 42
printf("%d", *valor); // Error 'valor' no es un puntero
En el ejemplo anterior, tenemos una variable que es un puntero triple (apunta (1) a un puntero que apunta (2) a un puntero que apunta (3) a un valor), por eso si queremos el valor debemos des-referenciar tres veces.
El operador de "dirección de" se puede usar con cualquier variable y obtiene un puntero al tipo de la variable:
int valor = 42;
int* puntero = &valor;
int** puntero_a_puntero = &puntero;
int*** puntero_a_puntero_a_puntero = &puntero_a_puntero;
En el ejemplo anterior, la "dirección de valor
" obtiene un puntero a entero (int*
) porque valor
es entero (int
); mientras que la "dirección de puntero
" obtiene un puntero a puntero a entero (int**
) porque puntero
es puntero a entero (int*
) etc…
Problemas.
Una vez aclarado cómo funcionan los operadores unarios *
y &
, veamos qué uso les has dado en tu código y por qué el uso es incorrecto.
En estas declaraciones de variables:
char saludo [10]="Amigo";
char* puntero = &saludo;
El tipo de saludo
es char[10]
(formación2 de diez caracteres), el nombre de una formación es un puntero al primer elemento de la misma, por lo tanto: sabiendo que saludo
es una formación de caracteres (char
) el nombre de la formación es un puntero a carácter (char*
).
Si obtenemos la dirección de la formación con el operador dirección-de, sabiendo que el nombre de la formación es un puntero a carácter (char*
) el resultado será puntero a puntero a carácter (char**
), ¡pero lo estás guardando en una variable de tipo puntero a carácter!
Sigamos:
*puntero = "Hola";
Sabemos que puntero
es un puntero a carácter (char*
) por lo que al des-referenciarlo obtenemos un carácter (char
), este carácter será el primer elemento de la formación2 a la que apunta puntero
.
Asignas al primer carácter de la formación a la que apunta puntero
el literal de texto "Hola"
que es de tipo char[5]
, y que es interpretado como puntero a carácter (char*
); es decir: en un carácter (char
) guardas un puntero a carácter (char*
).
Los punteros se guardan en variables de 32 o 64 bits3 pero los caracteres son de 8 o 16 bits3 así que se trunca parte del valor del puntero para guardar lo que se pueda, lo cuál da lugar a un carácter no imprimible (�
) cuando muestras la variable por pantalla.
Propuesta.
Si usases bien los operadores unarios *
y &
tu código debería parecerse a lo que ha mostrado SuperG280:
int main(void)
{
char saludo [10]="Amigo";
char* puntero = saludo; // SIN operador dirección-de
printf("Nuestro puntero apunta a: %p \n",puntero);
printf("La variable saludo esta en: %p \n",saludo);
if(saludo == puntero) // SIN operador dirección-de
{
printf("Las direcciones apuntan al mismo lugar: %p \n",puntero);
}
puntero = "Hola"; // SIN operador de des-referencia
printf("%s",saludo);
return 0;
}
1El asterisco *
se puede usar como operador de multiplicación (int i = 3 * 2;
) o como operador de des-referencia (int v = *x;
) el primero es el uso binario y el segundo es el uso unario. El et &
se puede usar como operador de AND binario (int i = 7 & 3;
) o como operador de dirección de (int *p = &x;
) el primero es el uso binario y el segundo es el uso unario.
2También conocida como arreglo o en inglés array.
3Dependiendo de la arquitectura del sistema u otros factores.