rareza constante del puntero typedef
por favor considere el siguiente código:
typedef struct Person* PersonRef;
struct Person {
int age;
};
const PersonRef person = NULL;
void changePerson(PersonRef newPerson) {
person = newPerson;
}
Por alguna razón, el compilador se queja de que el valor de solo lectura no se puede asignar. Pero la const
palabra clave no debería hacer que el puntero sea constante. ¿Algunas ideas?
Tenga en cuenta que
typedef int* intptr;
const intptr x;
no es lo mismo que:
const int* x;
intptr
es puntero a int. const intptr
es un puntero constante a int
, no un puntero a constante int
.
entonces, después de un puntero typedef, ¿ya no puedo hacerlo constante con el contenido?
Hay algunas formas feas, como la macro typeof de gcc :
typedef int* intptr;
intptr dummy;
const typeof(*dummy) *x;
pero, como ves, no tiene sentido si conoces el tipo que hay detrás intptr
.
const PersonRef person = NULL;
es
struct Person*const person= NULL;
entonces estás contrastando el puntero y no el objeto.
Si bien el problema ya está resuelto con las respuestas anteriores, olvido la razón por la cual...
Entonces, tal vez como regla general:
- Siempre
const
se refiere a su token predecesor. - En caso de que no exista tal, es "constante" su token sucesor.
Esta regla realmente puede ayudarle a declarar un puntero a punteros constantes o algo igualmente interesante.
De todos modos, con esto en mente, debería quedar claro por qué
struct Person *const person = NULL;
declara un puntero constante a una estructura mutable.
Piénselo, su typedef "agrupa" el struct Person
token con el puntero *
. Entonces, para escribir
const PersonRef person = NULL;
su compilador ve algo como esto (pseudocódigo):
const [struct Person *]person = NULL;
Como no queda nada const
, declara constante el token a su derecha struct Person *
.
Bueno, creo que esta es la razón por la que no me gusta ocultar punteros mediante typedefs, mientras que sí me gustan los typedefs como tales. ¿Qué pasa con la escritura?
typedef struct Person { ... } Person;
const Person *person; /*< const person */
Person *const pointer; /*< const pointer to mutable person */
y debería quedar bastante claro para los compiladores y los humanos lo que estás haciendo.