Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Puntero dentro de una estructura

Iniciado por player, 16 de Abril de 2010, 06:18:22 PM

« anterior - próximo »

player

Hola a todos.

He creado una estructura con el formato siguiente para crear luego una lista enlazada:

typedef struct
{
 string nombre;
 string apellidos;
 MiEstructura *siguiente;
}MiEstructura;

Si compilo, me sale el siguiente mensaje, refiriéndose a la línea marcada en negrita:

error: ISO C++ prohíbe la declaración de 'MiEstructura' sin tipo
error: expected ';' before '*' token

En cambio, si hago:

struct MiEstructura
{
 string nombre;
 string apellidos;
 MiEstructura *siguiente;
};

Puedo compilar perfectamente y el programa me funciona. A qué se debe ese mensaje de error cuando pongo el typedef? Gracias.

Mars Attacks

#1
Simplemente que, en el primer modo, el compilador aún no sabe qué es eso de MiEstructura (el del puntero que pones en negrita) hasta que termina de procesar todo lo que hay entre llaves. En el segundo modo ya sabe algo de ese tipo desde el principio.

Se me olvidaba: nada te impide hacer el typedef delante de tu segunda alternativa.

player

Gracias por la explicación, ya lo tengo claro.

Ruben

Hi,
CitarSimplemente que, en el primer modo, el compilador aún no sabe qué es eso de MiEstructura (el del puntero que pones en negrita) hasta que termina de procesar todo lo que hay entre llaves. En el segundo modo ya sabe algo de ese tipo desde el principio.

Se me olvidaba: nada te impide hacer el typedef delante de tu segunda alternativa.
creo que el anterior comentario no es muy acertado , por no decir que no ha dado pie con bola ^_^'
Citartypedef struct
{
  string nombre;
  string apellidos;
  MiEstructura *siguiente;
}MiEstructura;
en principio no te compila porque no has puesto un nombre a la estructura (despues de "struct"), no porque no encuentre una declaracion de MiEstructura. Deberia de compilarte de esta forma:
typedef struct MiEstructura
{
  string nombre;
  string apellidos;
  MiEstructura *siguiente;
}MiEstructura;

Aunque tambien puedes poner:
typedef struct FooBar
{
  string nombre;
  string apellidos;
  FooBar*siguiente;
}MiEstructura;

y te seguiria compilando.

Estas mezclando C y C++. En C para declarar una variable de tipo struct, tenias que poner siempre struct, lo cual era un coñazo. Asi que haces un typedef y listo (lo que has hecho en tu ejemplo). En C++ es diferente y directamente puedes declarar una estructura y usar ese nombre como un nuevo tipo sin tener que poner struct todas las veces que quieras declarar una variable de ese tipo. Asi que el hacer el typedef es redundante en C++. Asi tu ejemplo quedaria:

#include <iostream>

using namespace std;
struct MiEstructura
{
string nombre;
string apellidos;
MiEstructura *siguiente;
};

int main(int argc, char** argv)
{
MiEstructura miEstructuraA;
miEstructuraA.nombre = "Foo A";
miEstructuraA.apellidos = "Aar";

MiEstructura miEstructuraB;
miEstructuraB.nombre = "Foo B";
miEstructuraB.apellidos = "Bar";
miEstructuraB.siguiente = 0;

miEstructuraA.siguiente = &miEstructuraB;

std::cout << "miEstructuraA.nombre = " << miEstructuraA.nombre.c_str() << std::endl
  << "miEstructuraA.apellidos = " << miEstructuraA.apellidos.c_str() << std::endl
  << "miEstructuraA.siguiente->nombre = " << miEstructuraA.siguiente->nombre.c_str() << std::endl
  << "miEstructuraA.siguiente->apellidos = " << miEstructuraA.siguiente->apellidos.c_str() << std::endl;
return 0;
}

La unica reseña es que, puedes declarar una estructura con el mismo nombre que con una no estructura (funcion, etc...) por razones historicas heredadas de C. Asi que para hacer la "desambiguacion" (dios me pille confesao, si no existe ese palabro! :P) puedes poner delante del nombre del tipo estructura, "struct". Ejemplo:

struct Foo {
// ...
};
void Foo(int bar);


Un saludo,
Ruben

player

#4
Cita de: Ruben en 17 de Abril de 2010, 12:38:40 AM
creo que el anterior comentario no es muy acertado , por no decir que no ha dado pie con bola ^_^'
.
Bueno, se sobreentendía lo que quería decir.

Ya sé que eso es mezclar C con C++, yo nunca pongo el typedef, pero como algunos profesores retrasados "lo quieren así porque sino te quito nota" pues me ha tocado ponerlo forzadamente de esta forma:

typedef struct
{
  string nombre;
  string apellidos;
  MiEstructura *siguiente;
}MiEstructura;

y de ahí me ha surgido la duda,.

Gracias por tus ejemplos igualmente.

Saludos.

Ruben

Hi,
CitarBueno, se sobreentendía lo que quería decir.
Precisamente, si has sobreentendido algo de ese comentario es que no has entendido cual era el fallo, porque la explicacion dada en ese comentario esta mal. Por muy explicito que hubiera sido, esa no es la razon a tu problema.

Estabas declarando una estructura sin nombre y compilandolo en C++ (a juzgar por el error de compilacion que te daba), pero no es que no estuviese encontrando el miembro MiEstructura dentro de la declaracion de MiEstructura (que como se ve en el ejemplo que te he puesto no tiene problemas en encontrolarlo). En C++ no puedes tener estructuras sin nombre(con las uniones si), a diferencia de C. Por lo que tu ejemplo compila en C pero no en C++. En C++ es obligatorio poner un nombre a la estructura. Tan sencillo como eso. En C++ usar el idiom del typedef es redundante.

Un saudo,
Ruben

Mars Attacks

#6
Toda la razón, he patinado de lo lindo con la explicación. ¡Gracias por las correcciones!

Titonus

#7
Cita de: Ruben en 17 de Abril de 2010, 02:50:10 PM
Hi,
CitarBueno, se sobreentendía lo que quería decir.
Precisamente, si has sobreentendido algo de ese comentario es que no has entendido cual era el fallo, porque la explicacion dada en ese comentario esta mal. Por muy explicito que hubiera sido, esa no es la razon a tu problema.

Estabas declarando una estructura sin nombre y compilandolo en C++ (a juzgar por el error de compilacion que te daba), pero no es que no estuviese encontrando el miembro MiEstructura dentro de la declaracion de MiEstructura (que como se ve en el ejemplo que te he puesto no tiene problemas en encontrolarlo). En C++ no puedes tener estructuras sin nombre(con las uniones si), a diferencia de C. Por lo que tu ejemplo compila en C pero no en C++. En C++ es obligatorio poner un nombre a la estructura. Tan sencillo como eso. En C++ usar el idiom del typedef es redundante.

Un saudo,
Ruben


Realmente es que no está encontrando el miembro MiEstructura (puntero) ya que está declarando una estructura sin nombre, lo cual si puede hacerse en C++ si lo combinas con otra acción, y por tanto el nombre de la estructura no es MiEstructura sino un nombre interno que le asignará el compilador, de ahí el fallo seguramente.
En su caso MiEstructura sería el alias de la estructura al hacer el Typedef pero el problema es que está fallando la declaración previa de la estructura sin nombre y por tanto no puede hacerse el Typedef, que necesita un tipo bien declarado para asignar alias.
Entiendo que quieras decir que Typedef es redundante pero sólo en su caso, porque que esté o no puede cambiar el significado de lo que hacemos.

Ejemplos de esto que digo:


struct { int r, b, g; } Color; //define una variable Color de la estructura sin nombre
struct Color { int r, b, g; }; //define una estructura con nombre Color
struct Color { int r, b, g; } Color1; //define una estructura con nombre Color y una variable Color1 de dicho tipo
typedef struct { int r, b, g; } Color; //define una estructura sin nombre y le asigna alias Color para declarar variables luego
typedef struct Color { int r, b, g; } *PCOLOR; //define una estructura con nombre Color y le asigna alias PCOLOR para referirse a variables puntero de esta estructura

Ruben

Hi,
efectivamente, en C++ si haces un typedef sobre una clase(estructura o enum) anonima el nombre del tipo sera el que le asignes en el typedef, toda la razon. :)

Ahora, en C++ no es estandar declarar estructuras anonimas, aunque en C si esta permitido. Por tanto: "struct{int bar;} Foo; Foo foo;" o el ejemplo que has puesto "struct { int r, b, g; } Color;" no deberian compilar en C++ estandar.

Un saludo,
Ruben






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.