Recientemente tuve el placer de explicarle los consejos a un principiante de programación en C y me topé con la siguiente dificultad. Puede que no parezca un problema en absoluto si ya sabe cómo usar punteros, pero intente ver el siguiente ejemplo con una mente clara:
int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);
Para el principiante absoluto, la salida puede ser sorprendente. En la línea 2 él / ella acababa de declarar * bar como be & foo, pero en la línea 4 resulta que * bar es realmente foo en lugar de & foo!
La confusión, se podría decir, proviene de la ambigüedad del símbolo *: en la línea 2 se usa para declarar un puntero. En la línea 4 se usa como operador unario que obtiene el valor al que apunta el puntero. Dos cosas diferentes, ¿verdad?
Sin embargo, esta "explicación" no ayuda en absoluto a un principiante. Introduce un nuevo concepto al señalar una discrepancia sutil. Esta no puede ser la forma correcta de enseñarlo.
Entonces, ¿cómo lo explicaron Kernighan y Ritchie?
El operador unario * es el operador de indirección o desreferenciación; cuando se aplica a un puntero, accede al objeto al que apunta el puntero. [...]
La declaración del puntero ip,
int *ip
pretende ser un mnemotécnico; dice que la expresión*ip
es un int. La sintaxis de la declaración para una variable imita la sintaxis de las expresiones en las que puede aparecer la variable .
int *ip
debe leerse como " *ip
devolverá un int
"? Pero, ¿por qué la asignación después de la declaración no sigue ese patrón? ¿Qué pasa si un principiante quiere inicializar la variable? int *ip = 1
(léase: *ip
devolverá un int
y el int
is 1
) no funcionará como se esperaba. El modelo conceptual simplemente no parece coherente. ¿Me estoy perdiendo de algo?
Editar: Intentó resumir las respuestas aquí .
*
en una declaración es un token que significa "declarar un puntero", en expresiones es el operador de desreferencia, y que estos dos representan cosas diferentes que tienen el mismo símbolo (igual que el operador de multiplicación - mismo símbolo, significado diferente). Es confuso, pero cualquier cosa diferente al estado actual de las cosas será aún peor.
int* bar
hace que sea más obvio que la estrella es en realidad parte del tipo, no parte del identificador. Por supuesto, esto te lleva a diferentes problemas con cosas poco intuitivas como int* a, b
.
*
puede tener dos significados diferentes según el contexto. Al igual que la misma letra se puede pronunciar de manera diferente según la palabra en la que se encuentre, lo que dificulta aprender a hablar muchos idiomas. Si cada concepto / operación tuviera su propio símbolo, necesitaríamos teclados mucho más grandes, por lo que los símbolos se reciclan cuando tiene sentido hacerlo.
int* p
), al tiempo que advierte a su estudiante que no use declaraciones múltiples en la misma línea cuando hay punteros involucrados. Cuando el alumno haya entendido completamente el concepto de punteros, explíquele que la int *p
sintaxis es equivalente y luego explique el problema con varias declaraciones.