Cómo hacer una estructura externa y definir su typedef

6 minutos de lectura

avatar de usuario
Simar

Estoy tratando de implementar algoritmos de árbol en C. Declaré una estructura externa en un archivo de encabezado que es completamente independiente (b_tree_ds.h). Ahora planeo importar el archivo en todos los archivos fuente que quieran usar esta estructura. Entonces debo declararlo usando extern en el encabezado.

Ahora el problema es que también quiero definir su typedef. el compilador da error de múltiples clases de almacenamiento. ¿Cómo debo hacer eso?

typedef extern struct node {
    struct node* left;
    struct node* right;
    int key;    // contains value
}NODE;

El problema real es el siguiente, que todavía no puedo solucionar??? Recientemente aprendí cómo podemos usar múltiples archivos fuente con archivos de encabezado para hacer que el código sea portátil y jerárquico. Para hacerlo, me cansé de crear mi programa de árbol usando este principio. Aquí están mis archivos

b_tree_ds.h – Esto contendrá un declaración de la estructura de datos del nodo de un árbol, que se puede llamar a varias funciones que implementan diferentes funciones del árbol (que pueden estar en diferentes archivos fuente)

typedef struct node {
    struct node* left;
    struct node* right;
    int key;    // contains value
}NODE;

Cuando intento agregar un externo como en typedef extern struct node da un error de clase de almacenamiento múltiple, pero si lo pierdo, aparece un error para varias definiciones.

Aquí están mis otros archivos fuente

traverse.h – contiene la declaración de la función poligonal

void traverse_print (NODE* p);

Aquí también recibo un error de identificador desconocido NODE

traverse.c – contiene la definición de esa función

#include <stdio.h>
#include "b_tree_ds.h"
#include "traverse.h"

void traverse_print(NODE* p)
{
    if(p->left != NULL)
    {
        traverse_print(p->left);
    }

    if (p->right != NULL)
    {
        traverse_print(p->right);
    }

    printf ("\n%d",p->key);
}

Finalmente main.c

#include <stdio.h>
#include "traverse.h"

void main()
{
    // input
    NODE p;

    printf("\nInput the tree");
    input_tree (&p);

    printf("\n\nThe tree is traversing ...\n")
    traverse_print(&p);
}

void input_tree (NODE *p)
{
    int in;
    int c;
    NODE *temp;

    printf("\n Enter the key value for p: ");
    scanf("%d", &in);
    p->key  =in;
    printf ("\n\nIn relation to node with value %d",in);
    printf ("Does it have left child (Y/N): ")
    if ((c = getchar()) == Y);
    {
        //assign new memory to it.
        temp = (NODE *)malloc(sizeof(NODE));
        input_tree(temp);
    }
    printf ("\n\nIn relation to node with value %d",p->key);

    printf ("\nDoes it have right child (Y/N): ")
    if ((c = getchar()) == Y);
    {
        //assign new memory to it.
        temp = (NODE *)malloc(sizeof(NODE));
        input_tree(temp);
    }
}

Este es mi primer intento de tal práctica, por favor sugiera si la estructuración de mi programa es buena o debería intentar algo más.

avatar de usuario
cnicutar

No puedes hacer una estructura extern. Simplemente defínalo en un encabezado protegido de include-guard e incluya ese encabezado donde lo necesite.

EDITAR para SquareRootOfTwentyThree

Yo uso esas termias en de la siguiente manera:

Una definición de tipo de estructura describe los miembros que forman parte de la estructura. Contiene la palabra clave struct seguida de un identificador opcional (la etiqueta de estructura) y una lista de miembros entre llaves.

Una declaración de estructura tiene la misma forma que una definición de estructura, excepto que la declaración no tiene una lista de miembros entre llaves.

Así que “definición” es exactamente lo que quise decir.

  • En general, la definición implica la asignación de almacenamiento, lo que normalmente no debería ocurrir en un encabezado (sin importar si está protegido). En los encabezados haces declaraciones. Por lo tanto, su respuesta es confusa. Argumente con referencias a los estándares C, no a alguna interpretación que se encuentre en la web.

    – Raíz cuadrada de veinte y tres

    17 de marzo de 2012 a las 15:02

  • @SquareRootOfTwentyThree Creo que eres quisquilloso. Mantengo mi respuesta: en este contexto, “definir” es muy claro, no se puede confundir con nada más.

    – cnicutar

    17 de marzo de 2012 a las 15:15


  • No es claro. Literalmente estás diciendo que el usuario debería definir la estructura en el encabezado. Solo cámbialo a declarar y esta bien..

    – cuanto

    16/10/2014 a las 21:08

  • ¿No puede externizar una estructura como externó una variable (con ligeros cambios)? Cree un encabezado extern.h que contenga extern Sruct1 S, cree otro encabezado struct.h que contenga la estructura typedef Sruct1 y finalmente declare la estructura Sruct1 S en cualquier archivo .c único. Incluya el encabezado extern.h y struct.h en todos los archivos que necesita usar esta estructura. Ahora se puede acceder a esta estructura desde cualquier lugar

    – AlphaGoku

    7 de abril de 2016 a las 6:48

  • Lo pienso así: la declaración especifica el identificador. La definición especifica el diseño. La creación de instancias implica la asignación de almacenamiento. No hay almacenamiento asignado en una definición. Acepté esto como respuesta.

    – joe promedio

    19/10/2016 a las 15:03

avatar de usuario
Kerrek SB

En C, las estructuras no tienen vínculos, solo los objetos y las funciones los tienen. Entonces puedes escribir esto:

// header file 'node.h'

typedef struct node_
{
    /* ... */
} node;

extern node root_node;

Luego proporcione una implementación en algún lugar:

// source file

#include <node.h>

node root_node;

  • Solo los objetos lo hacen 😕 Entonces, ¿también incluye funciones allí?

    – cnicutar

    17 de marzo de 2012 a las 12:39

  • @cnicutar: Sí, supongo que sí 🙂 Puedes tomar la dirección de una función, ¿no?

    – KerrekSB

    17 de marzo de 2012 a las 12:46


  • Bueno, entonces hay un problema, el estándar dice en alguna parte: Un identificador puede denotar un objeto; Una función; una etiqueta o un miembro de una estructura, unión o enumeración; un nombre typedef; un nombre de etiqueta; un nombre de macro; o un parámetro macro. Entonces puedo ver una distinción entre objeto y función.

    – cnicutar

    17 de marzo de 2012 a las 12:53


  • ¿Qué son los objetos en C?

    – Pithikos

    16 de enero de 2015 a las 17:44

  • @Pithikos: cosas que tienen almacenamiento y que pueden ser valores. Por ejemplo, un int.

    – KerrekSB

    16 de enero de 2015 a las 21:33


avatar de usuario
anantha krishnan

En su archivo de encabezado, declare node.h así

#ifndef NODE_H
#define NODE_H

#ifdef  __cplusplus
extern "C" {
#endif

typedef struct node {
        struct node* left;
        struct node* right;
        int key;    // contains value
    }NODE;


#ifdef  __cplusplus
}
#endif

#endif  /* NODE_H */  

puede incluir este archivo de encabezado en cualquier programa c y usarlo como

NODE* newNode = NULL;

  • Esto produce un error error: varias clases de almacenamiento en los especificadores de declaración

    – simar

    17 de marzo de 2012 a las 12:41

  • extern "C" {} solo funciona si está utilizando un compilador de C++.

    – Kaiser Katze

    22 de agosto de 2018 a las 3:39

¿Ha sido útil esta solución?