26

I'm trying to implement tree algorithms in C. I have declared a extern struct in a header file that is completely independent (b_tree_ds.h). Now I plan to import the file in all source files that want to use this struct. So I must declare it using extern in header.

Now the problem is thhat I want to define its typedef as well. the compiler gives error of multiple storage classes. How should I do that.

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

The actual problem is as follow, which I still can't fix??? I recently learnt how can we use multiple source files with header files to make code portable and hierarchical. In order to do so, I tired creating my tree program using this principal. Here are my files

b_tree_ds.h - This will contain a declaration of datastructure of node of a tree, which can be called to various functions implementing different functionality of the tree (which may be in different source files)

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

When i try adding a extern as in typedef extern struct node it gives a error of multiple storage class but if I miss it, I get error for multiple definitions.

Here are my other source files

traverse.h - contains declaration of traverse function

void traverse_print (NODE* p);

Here also I get error for unknown identifier NODE

traverse.c - contains definition to that function

#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);
}

Finally 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);
    }
}

This is my first attempt to such practice, please suggest is the structuring of my program good or should I try something else.

simar
  • 544
  • 2
  • 7
  • 15

3 Answers3

34

You can't make a struct extern. Just define it in an include-guard protected header and include that header everywhere you need it.

EDIT for SquareRootOfTwentyThree

I use those therms in the following way:

A structure type definition describes the members that are part of the structure. It contains the struct keyword followed by an optional identifier (the structure tag) and a brace-enclosed list of members.

A structure declaration has the same form as a structure definition except the declaration does not have a brace-enclosed list of members.

So "definition" is exactly what I meant.

Community
  • 1
  • 1
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 2
    In general, definition implies allocation of storage, which should typically not happen in a header (no matter if it is guarded). In headers you do declarations. Your answer is therefore confusing. Please argument with references to the C standards, not to some interpretation found on the web. – SquareRootOfTwentyThree Mar 17 '12 at 15:02
  • @SquareRootOfTwentyThree I think you're nitpicking. I stand by my answer: in this context "define" is crystal clear, you can't confuse it with anything else. – cnicutar Mar 17 '12 at 15:15
  • 1
    It's not clear. You're literally saying that the user should _define_ the struct in the header. Just change it to _declare_ and it's fine.. – quant Oct 16 '14 at 21:08
  • cant you extern a struct like how you extern a variable(with slight changes)? Create a header extern.h that contains extern Sruct1 S,Create another header struct.h that contains the typedef struct Sruct1,then finally declare the struct Sruct1 S in any single .c file. Include header extern.h & struct.h in all files that this struct needs to be used. This struct now can be accessed anywhere – AlphaGoku Apr 07 '16 at 06:48
  • I think of it like this: Declaration specifies identifier. Definition specifies layout. Instantiation implies allocation of storage. There is no storage allocated in a definition. Accepted this as answer. – average joe Oct 19 '16 at 15:03
33

In C, structures have no linkage, only objects and functions do. So you can write this:

// header file 'node.h'

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

extern node root_node;

Then provide an implementation somewhere:

// source file

#include <node.h>

node root_node;
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    *Only objects do* :-? So you include functions there too ? – cnicutar Mar 17 '12 at 12:39
  • 1
    @cnicutar: Yeah, I guess I do :-) You can take the address of a function, non? – Kerrek SB Mar 17 '12 at 12:46
  • Well, there's an issue then, the standard says somewhere: *An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter*. So I can see a distinction between object and function. – cnicutar Mar 17 '12 at 12:53
  • 2
    What are objects in C? – Pithikos Jan 16 '15 at 17:44
  • 2
    @Pithikos: Things which have storage and which can be values. E.g. an `int`. – Kerrek SB Jan 16 '15 at 21:33
  • I've been trying to figure this out for a while. I forgot the name after `struct` ... :( – IAbstract Dec 13 '16 at 02:35
  • If 'object' is your word for things that are linked against, is 'symbol' a more correct word? Is that what you are searching for because C has no concept of objects? – Timothy John Laird Jan 26 '21 at 16:22
3

In your header file declare node.h like this

#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 */  

you can include this header file in any c program and use it like

NODE* newNode = NULL;
Anantha Krishnan
  • 3,068
  • 3
  • 27
  • 37