By r_goyal


2013-09-06 12:58:41 8 Comments

I am a beginner in C programming and I know the difference between struct type declaration and typedef struct declaration. I came across to know an answer saying that if we define a struct like:

typedef struct { 
    some members;
} struct_name;

Then it will be like providing an alias to an anonymous struct (as it is not having a tag name). So it can't be used for forward declaration. I don't know what the forward declaration means.

Also, I wanted to know that for the following code:

typedef struct NAME { 
    some members;
} struct_alias;

Is there any difference between NAME and struct_alias? Or are both equal as struct_alias is an alias of struct NAME ?

Furthermore, can we declare a variable of type struct NAME like these:

struct_alias variable1;

and/or like:

struct NAME variable2;

or like:

NAME variable3; 

5 comments

@Sergey L. 2013-09-06 13:05:54

struct forward declarations can be useful when you need to have looping struct declarations. Example:

struct a {
    struct b * b_pointer;
    int c;
};

struct b {
    struct a * a_pointer;
    void * d;
};

When struct a is declared it doesn't know the specs of struct b yet, but you can forward reference it.

When you typedef an anonymous struct then the compiler won't allow you to use it's name before the typedef.

This is illegal:

struct a {
    b * b_pointer;
    int c;
};

typedef struct {
    struct a * a_pointer;
    void * d;
} b;

// struct b was never declared or defined

This though is legal:

struct a {
    struct b * b_pointer;
    int c;
};

typedef struct b {
    struct a * a_pointer;
    void * d;
} b;

// struct b is defined and has an alias type called b

So is this:

typedef struct b b;
// the type b referes to a yet undefined type struct b

struct a {
    b * struct_b_pointer;
    int c;
};

struct b {
    struct a * a_pointer;
    void * d;
};

And this (only in C, illegal in C++):

typedef int b;

struct a {
    struct b * struct_b_pointer;
    b b_integer_type;
    int c;
};

struct b {
    struct a * a_pointer;
    void * d;
};

// struct b and b are two different types all together. Note: this is not allowed in C++

@r_goyal 2013-09-06 14:17:38

but what about the NAME ant struct_alias?? and what if i wrote " struct b b_pointer " in "struct a" declaration inspite of "bb_pointer"??

@Sergey L. 2013-09-06 14:21:28

@akash_sinha13134 that would be valid if struct b will be defined later. But not if you typedef an anonymous struct to b. typedef struct b { struct a * a_pointer; void * d; } b; would be valid. typedef names are not in the same namespace as struct names. You can have a struct b and a type b that are completely different. I think some confusion here comes from the fact that C++ does that typedef by default - C does not.

@Michael Beer 2017-12-06 10:23:14

As others stated before, a forward declaration in C/C++ is the declaration of something with the actual definition unavailable. Its a declaration telling the compiler "there is a data type ABC".

Lets pretend this is a header for some key/value store my_dict.h :

...
struct my_dict_t;
struct my_dict_t* create();

char* get_value(const struct my_dict_t* dict, const char* name);
char* insert(struct my_dict_t* dict, const char* name, char* value);
void destroy(struct my_dict_t* dict);
...

You dont know anything about my_dict_t, but actually, for using the store you dont need to know:

#include "my_dict.h"
...
struct my_dict_t* dict = create();
if(0 != insert(dict, "AnEntry", strdup("AValue"))) {
    ...
}
...

The reason for this is: You are only using POINTERS to the data structure.

POINTERS are just numbers, and for dealing with them you dont need to know what they are pointing at.

This will only matter if you try to actually access them, like

struct my_dict_t* dict = create();
printf("%s\n", dict->value);  /* Impossible if only a forward decl is available */

So, for implementing the functions, you require an actual definition of my_struct_t. You might do this in the source file my_dict.c like so:

#include "my_dict.h"

struct my_dict_t {
    char* value;
    const char* name;
    struct my_dict_t* next;
}

struct my_dict_t* create() {
    return calloc(1, sizeof(struct my_dict_t));
}

This is handy for several situations, like

  • For resolving circular type dependencies, like Sergei L. explained.
  • For encapsulation, like in the example above.

So the question that remains is: Why cant we just omit the forward declaration at all when using the functions above? In the end, it would suffice for the compiler to know that all dict are pointers.

However, the compiler does perform type checks: It needs to verify that you don't do something like

...
int i = 12;
char* value = get_value(&i, "MyName");
...

It does not need to know how my_dict_t looks like, but it needs to know that &i is not the type of pointer get_value() expects.

@dasblinkenlight 2013-09-06 13:09:44

Forward declaration is a promise to define something that you make to a compiler at the point where the definition cannot be made. The compiler can use your word to interpret other declarations that it would not be able to interpret otherwise.

A common example is a struct designed to be a node in a linked list: you need to put a pointer to a node into the struct, but the compiler would not let you do it without either a forward declaration or a tag:

// Forward declaration
struct element;
typedef struct {
    int value;
    // Use of the forward declaration
    struct element *next;
} element; // Complete definition

and so it cant be used for forward declaration

I think that author's point was that giving your struct a tag would be equivalent to a forward declaration:

typedef struct element {
    int value;
    // No need for a forward declaration here
    struct element *next;
} element;

@r_goyal 2013-09-06 14:29:52

does it mean dat typedefs donot allow the typedefined identifier to be refferenced before they are typedefined.. i did some more research and came to know just dis.. and since we have to declare the typedef'ed identifier before the typedef declaration of struct (if that is wat is called FORWARD DECLARATION) then compiler wont understand as to what is being declared??? or else will there be a collision in as in your example between struct element; and typedef struct{}element; ??

@r_goyal 2013-09-06 14:33:34

@dasblinkenlight.. + i think i got the answer dat if we dont have a tag name for a struct template then we cant forwaard declare it coz there is nothing to refference to... like if we need to declare and use a struct at a line of programme and dat struct is defined a hundred of lines later den we wont be having a tagname to refference to forward declare it.... thanks by the way..

@dasblinkenlight 2013-09-06 14:33:47

@akash_sinha13134 "does it mean that typedefs do not allow the typedef-ed identifier to be referenced before they are typedef-ed"? Correct. "will there be a collision in as in your example between struct element; and typedef struct{}element;" No, there would be no collision: the example compiles and runs fine - take a look.

@dasblinkenlight 2013-09-06 14:37:12

@akash_sinha13134 Your understanding is correct. An additional situation when you want to forward-declare a struct is when you want to declare a pointer to it, without having to bring in the actual definition of a structure. This lets you save on compile-time dependencies in situations when you treat a struct as a "black box" pointed to by a pointer, i.e. when you do not need to know its internals.

@r_goyal 2013-09-06 14:54:05

thanks @dasblinkenlight... but how does it save the compile time dependencies?? coz whenever i refference the struct for forward declaration, the compiler will look forward for the location where the struct is defined in the program... den how cum it save compile time dependencies..i cant understand it..

@dasblinkenlight 2013-09-06 15:01:30

@akash_sinha13134 If all you need is a pointer, the compiler will not look for the struct to be defined in the same translation unit. You can define it in another file, create it, and pass a pointer to a function that has no idea of the internal structure of your struct.

@r_goyal 2013-09-06 15:02:55

@dasblinkenlight.. and in the code(on ideone) at line e2.next=&e1; does the line means dat struct e2 = struct e1 coz printf("%d %d",e1.value,e2.value); is printing 123 0

@dasblinkenlight 2013-09-06 15:09:21

@akash_sinha13134 No, it does not mean that: e2.value is uninitialized, only e1.value is meaningful. That line assigns e2.next a pointer to e1.

@r_goyal 2013-09-06 15:15:25

also when i am running above code in my offline devC++(with mingw) compiler its showing a warning "[Warning] assignment from incompatible pointer type [enabled by default]".. i didnt understand why?

@dasblinkenlight 2013-09-06 15:17:49

@akash_sinha13134 Neither do I.

@Marcin Łoś 2013-09-06 13:06:00

Forward declaration is a declaration preceeding an actual definition, usually for the purpose of being able to reference the declared type when the definition is not available. Of course, not everything may be done with the declared-not-defined structure, but in certain context it is possible to use it. Such type is called incomplete, and there are a number of restrictions on its usage. For example:

struct X; // forward declaration

void f(struct X*) { }  // usage of the declared, undefined structure

// void f(struct X) { }         // ILLEGAL
// struct X x;                  // ILLEGAL
// int n =sizeof(struct X);     // ILLEGAL

// later, or somewhere else altogether
struct X { /* ... */ };

This can be useful e.g. to break circular dependencies, or cut down the compilation time, as the definitions are usually significantly larger, and so more resources are required to parse it.

In your example, struct NAME and struct_alias are indeed equivalent.

struct_alias variable1;
struct NAME variable2;

are correct;

NAME variable3;

is not, as in C the struct keyword is required.

@r_goyal 2013-09-06 14:13:02

@marcin.. but in C, on using typedef i can omit the use of struct keyword as in struct_alias variable1; why cant i omit struct keyword before NAME?

@Allan Jude 2017-12-05 04:12:49

@r_goyal You can omit it for the ALIAS, not the NAME. A typdef creates the alias, which is the substitute for 'struct NAME'

@Gangadhar 2013-09-06 13:03:05

struct_alias and struct NAME are same ,struct_alias is an alias to struct NAME

These both are same and allowed

struct_alias variable1;  

struct NAME variable1; 

this is illegal

NAME variable3;   

See this article on Forward declaration

Related Questions

Sponsored Content

6 Answered Questions

[SOLVED] What is the difference between 'typedef' and 'using' in C++11?

17 Answered Questions

[SOLVED] What is the difference between const int*, const int * const, and int const *?

23 Answered Questions

27 Answered Questions

13 Answered Questions

[SOLVED] What is a typedef enum in Objective-C?

2 Answered Questions

[SOLVED] C forward declaration for typedef struct

15 Answered Questions

[SOLVED] Why should we typedef a struct so often in C?

  • 2008-10-31 07:14:03
  • Manoj Doubts
  • 495483 View
  • 378 Score
  • 15 Answer
  • Tags:   c struct typedef

18 Answered Questions

[SOLVED] What's the difference between struct and class in .NET?

8 Answered Questions

[SOLVED] Difference between 'struct' and 'typedef struct' in C++?

  • 2009-03-04 20:41:12
  • criddell
  • 495827 View
  • 801 Score
  • 8 Answer
  • Tags:   c++ struct typedef

Sponsored Content