I stumbled upon a very strange feature of C: you can declare a named structure inside another structure provided that declare a member variable of that type at the same time:
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st { /* <- named struct */
int capacity;
int load;
} battery;
};
The inner structure becomes then available outside the structure as any other type, rendering strange code like this perfectly valid:
struct Robot_st my_robot = {2, 3, {200, 50}};
struct BatteryStatus_st battery_snapshot; /* <- use of inner struct */
memcpy(
&battery_snapshot,
&my_robot.battery,
sizeof(struct BatteryStatus_st)
);
printf("robot position: %d,%d\n", my_robot.pos_x, my_robot.pos_y);
printf("battery load: %d%%\n", battery_snapshot.load);
Nesting unnamed structures feels right, because as you cannot access the type later, there is no confusion about the scope of the type. The above code is also not valid in C++, although the nested declaration is, because C++ understands it as a type in the namespace of the outer structure, so you need to access it using
struct Robot_st::BatteryStatus_st battery_snapshot;
which, despite feeling strange to declare both a type and a member at the same time, makes more sense.
So why is this construct valid in C? Is there any history/reason behind? Is there a use case for such a construct? (Mine was a mistake that led to failures, thus the question.)
Link to full working code.
Such constructs were allowed in C originally because structure names occupied a universe all their own which never had any sort of scoping rules applied to it [struct member names did too, by the way, which is why some of the structure types in older standard libraries have prefixes on their members]. Because some code exists which uses structure names in a fashion inconsistent with scoping, the standard could not be changed to prohibit such usage without breaking existing code. While there are times when it's worthwhile to break existing code (e.g. to rid C of the abomination called gets) this really isn't one of them.
In addition to the other two answers, here is a real usecase that calls for such a named inner struct:
struct LinkedList {
//data members stored once per list
struct LinkedListNode {
//data members for each entry of the list
struct LinkedListNode *next;
} *head, *tail;
};
Its hard to write a more concise definition for the structure of a linked list.
An unnamed inner struct won't do: The code that inserts something into the linked list will likely have to declare local variables with node pointers. And there is no point in declaring the node structure outside of the linked list structure.
Well, this is legal in C:
struct BatteryStatus_st {
int capacity;
int load;
};
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st battery;
};
and, as you pointed out, it is effectively identical to the code you posted (since C doesn't have the namespace/scoping rules introduced in C++).
If moving the "inner" type inside doesn't change anything, but may sometimes clarify intent, it would seem odd to prohibit it.
Let's say I have this structure:
struct OuterStruct
{
int a;
struct InnerStruct
{
int i;
int j;
} b;
} s;
Now I can access s.a, and I can even save it in a variable, to better handle it, pass it to functions, ...
int sa = s.a;
Well, now I want to do the same with s.b, and to do so I need InnerStruct to have a name!
???? sb = s.b; // here I have to use InnerStruct, otherwise sb would have no valid type!
The alternative would be to declare InnerStruct outside of OuterStruct, and then putting an instance of it inside as member of OuterStruct. But this would hide the fact that InnerStruct belongs to OuterStruct, making your intent less clear.
Related
My understanding of C is that there are two separate namespaces, one for tags (such as for structs) and one for all other variables (including structs). Using typedef before a struct definition will then treat the struct variable as a type, so if you use
struct car_part {/* Code Here */} CarPart;
(where CarPart is optional)
you'd have to use
struct car_part engine;
to declare a car part.
Whereas if you used a typedef with
typedef car_part {/* Code Here */} CarPart;
you can now use
CarPart engine;
instead.
typedef struct tag {/* Code here */} struct_name;
1) Is there any difference between declaring the actual variable before or after the block code? i.e.
typedef struct tag struct_name
{
/* Code here */
};
vs
typedef struct tag
{
/* Code here*/
} struct_name;
2) Are there ever any advantages to not using typedef for a struct definition, even if you won't declare another struct variable of that type?
3) The following code says that there's a syntax error C2061 with the identifier Node, but I don't see anything wrong with it. I tried adding the keyword struct before each element declaration, but that only gave more errors. Any thoughts?
typedef struct Ticket
{
char customer_name[20];
int ticket_number;
} Ticket;
typedef struct Node
{
Ticket ticket_info;
Node *next;
Node *previous;
} Node;
typedef struct Queue
{
Ticket *front;
Ticket *rear;
int queue_count;
} Queue;
edit: fixed first two lines of code to explicitly state where the element declarations should be.
There are actually four name-spaces in C (although this depends on a particular way of counting, and some include macro names as a fifth space, which I think is a valid way to think about them):
goto labels
tags (struct, union, and enum)
the actual members of a struct or union type (one per type, hence you could count this as "many" instead of "one" name space)
all other ("ordinary") identifiers, such as function and variable names and the names made to be synonyms for other types via typedef.
While it should (in theory) be possible to have separate spaces for struct vs union, for instance, C does not, so:
struct foo; union foo; /* ERROR */
is invalid. Yet:
struct foo { int a, b; };
struct bar { char b; double a; };
is just fine, showing that the members of the two different struct types are in different name-spaces (so again this makes the count of "4 name-spaces" above suspect :-) ).
All that aside, C has some moderately (and in some ways unnecessarily) complicated, but quite workable in practice, rules for how struct types work.
Each struct creates a new type unless it refers back to an existing type. The struct keyword may be followed by an identifier, or just an open brace {. If there is just an open brace, the struct creates a new type:
struct { ... } X; /* variable X has a unique type */
If there is an identifier, the compiler must look at the (single) tag name-space to see if that name is already defined. If not, the struct defines a new type:
struct blart { ... } X; /* variable X has type <struct newname>, a new type */
If the identifier is already present, generally this refers back to the existing type:
struct blart Y; /* variable Y has the same type as variable X */
There is one special exception, though. If you're in a new scope (such as at the beginning of a function), a "vacuous declaration"—the struct keyword, followed by an identifier, followed by a semicolon—"clears out" the previous visible type:
void func(void) {
struct blart; /* get rid of any existing "struct blart" */
struct blart { char *a; int b; } v;
Here v has a new type, even if struct blart was already defined outside func.
(This "vacuous declaration" trick is mostly useful in obfuscated code contests. :-) )
If you're not at a new scope, a vacuous declaration serves the purpose of declaring that the type exists. This is mainly useful to work around a different issue, which I will cover in a moment.
struct blart;
Here struct blart alerts you (and the compiler) that there is now a type named "struct blart". This type is merely declared, meaning that the struct type is "incomplete", if struct blart has not yet been defined. This type is defined (and "complete") if struct blart has been defined. So:
struct blart { double blartness; };
defines it, and then any earlier or later struct blarts refer to the same type.
Here's why this sort of declaration is useful. In C, any declaration of an identifier has scope. There are four possible scopes: "file", "block", "prototype", and "function". The last one (function scope) is exclusively for goto labels, so we can ignore it from here on. That leaves file, block, and prototype scopes. File scope is a technical term for what most people think of as "global", in contrast with "block scope" which is "local":
struct blart { double blartness } X; /* file scope */
void func(void) {
struct slart { int i; } v; /* block scope */
...
}
Here struct blart has file scope (as does "global" variable X), and struct slart has block scope (as does "local" variable v).
When the block ends, struct slart goes away. You can no longer refer to it by name; a later struct slart creates a new and different type, in exactly the same way that a later int v; creates a new v, and does not refer to the v within the block scope inside function func.
Alas, the committee that designed the original C standard included (for good reason) one more scope, inside the function prototype, in a way that interacts rather badly with these rules. If you write a function prototype:
void proto(char *name, int value);
the identifiers (name and value) disappear after the closing parenthesis, just as you'd expect—you wouldn't want this to create a block-scope variable called name. Unfortunately, the same happens with struct:
void proto2(struct ziggy *stardust);
The name stardust goes away, but so does struct ziggy. If struct ziggy did not appear earlier, that new, incomplete type that is created inside the prototype, has now been removed from all human reach. It can never be completed. Good C compilers print a warning here.
The solution is to declare the struct—whether complete or not [*]—before writing the prototype:
struct ziggy; /* hey compiler: "struct ziggy" has file scope */
void proto2(struct ziggy *stardust);
This time, struct ziggy has an already-existing, visible declaration to refer back to, so it uses the existing type.
[* In header files, for instance, you often don't know if the header that defines the struct has been included, but you can declare the struct yourself, and then define protoypes that use pointers to it.]
Now, as to typedef...
The typedef keyword is syntactically a storage-class specifier, like register and auto, but it acts quite weird. It sets a flag in the compiler that says: "change variable declarations into type-name aliases".
If you write:
typedef int TX, TY[3], *TZ;
the way that you (and the compiler) can understand this is to start by removing the typedef keyword. The result needs to be syntactically valid, and it is:
int TX, TY[3], *TZ;
This would declare three variables:
TX has type int
TY has type "array 3 of int"
TZ has type "pointer to int"
Now you (and the compiler) put the typedef back in, and change "has" to "is another name for":
TX is another name for type int
TY is another name for "array 3 of int"
TZ is another name for "pointer to int"
The typedef keyword works with struct types in exactly the same way. It's the struct keyword that creates the new type; then typedef changes the variable declaration(s) from "has type ..." to "is another name for type ...". So:
typedef struct ca ca_t;
starts by either creating new type, or referring back to existing type, struct ca as usual. Then, instead of declaring a variable ca_t as having type struct ca, it declares the name as another name for the type struct ca.
If you omit the struct tag name, you are left with only two valid syntactic patterns:
typedef struct; /* note: this is pointless */
or:
typedef struct { char *top_coat; int top_hat; } zz_t, *zz_p_t;
Here, struct { creates a new type (remember, we said this way back at the beginning!), and then after the closing }, the identifiers that would have declared variables, now make type-aliases. Again, the type was actually created by the struct keyword (although it hardly matters this time; the typedef-names are now the only ways to refer to the type).
(The reason the first pointless pattern is the way it is, is that without the braces, the first identifier you stick in is the struct-tag:
typedef struct tag; /* (still pointless) */
and thus you haven't omitted the tag after all!)
As for the last question, about the syntax error, the problem here is that C is designed as a "single pass" language, where you (and the compiler) never have to look very far forward to find out what something is. When you attempt something like this:
typedef struct list {
...
List *next; /* ERROR */
} List;
you've given the compiler too much to digest at once. It starts by (in effect) ignoring the typedef keyword except to set the flag that changes the way variables will be declared. This leaves you with:
struct list {
...
List *next; /* ERROR */
}
The name List is simply not yet available. The attempt to use List *next; does not work. Eventually the compiler would reach the "variable declaration" (and because the flag is set, change it to a type-alias instead), but it's too late by then; the error has already occurred.
The solution is the same as with function prototypes: you need a "forward declaration". The forward declaration will give you an incomplete type, until you finish defining the struct list part, but that's OK: C lets you use incomplete types in a number of positions, including when you want to declare a pointer, and including with typedef alias-creation. So:
typedef struct list List; /* incomplete type "struct list" */
struct list { /* begin completing "struct list" */
...
List *next; /* use incomplete "struct list", through the type-alias */
}; /* this "}" completes the type "struct list" */
This gains relatively little over just writing struct list everywhere (it saves a bit of typing, but so what? well, OK, some of us suffer a bit of carpal tunnel / RSI issues :-) ).
[Note: this last segment is going to cause controversy... it always does.]
In fact, if you mentally replace struct with type, C code becomes a whole lot nicer to "strongly typed language" fans. Instead of the terrible [%], weak-sauce:
typedef int distance; /* distance is measured in discrete units */
typedef double temperature; /* temperatures are fractional */
they can write:
#define TYPE struct
TYPE distance;
TYPE temperature;
These, being incomplete types, are truly opaque. To create or destroy or indeed do anything with a distance value you must call a function (and—for most variables anyway; there are some exceptions for external identifiers—use pointers, alas):
TYPE distance *x = new_distance(initial_value);
increase_distance(x, increment);
use_distance(x);
destroy_distance(x);
Nobody can write:
*x += 14; /* 3 inches in a dram, 14 ounces in a foot */
It simply won't compile.
Those who are a bit less bondage-and-discipline with their type systems can relax the constraints by completing the type:
TYPE distance { int v; };
TYPE temperature { double v; };
Of course, now "cheaters" can do:
TYPE distance x = { 0 };
x.v += 14; /* 735.5 watts in a horsepower */
(well, at least that last comment is correct).
[% Not really that terrible, I think. Some seem to disagree.]
1) The difference between those two blocks of code is that the first one is invalid syntax, while the second one is good and useful. I use the second one in order to define a struct and also define a typedef for the struct at the same time. My code has stuff that looks like this:
typedef struct Dog {
int age, barks;
} Dog;
After that line, I can define dogs with Dog mydog; or struct Dog mydog;.
It's important to understand that the code above is doing two things. It is defining a type named struct Dog, and then it is defining a type named Dog that just refers to struct Dog. You could split that into two separate steps like this:
struct Dog {
int age, barks;
};
typedef struct Dog Dog;
2) I always use the typedef as shown above in the first block of code and have found no problem with it. I would say there are no advantages to leaving out the typdef. Just for the record, if you want to leave out the typedef and only define a struct, then you code would be:
struct Dog {
int age, barks;
};
If you do it that way, you can only make new dogs by typing struct Dog mydog;; in other words, the name of the type is only struct Dog and Dog does not name a type.
3) The problem is that you are trying to use "Node" inside the definition of "Node". That would be a circular definition. You can fix everything by just writing it like this:
struct Node;
typedef struct Node
{
struct Node * next;
struct Node * previous;
} Node;
1) Your first example is invalid syntax. The correct way is this:
typedef struct tag {
/* ... */
} struct_name;
2) Using typedefs for structures makes them seem like atomic data types. It also allows for you to make the types opaque (so other code blocks can't see the inside of the structure). Personally, I find typedef-ing of structures to be a very bad habit (since the struct identifier helps differentiate structures and typedefs of atomic types).
3) You are trying to use the typedef'd version of the node structure inside itself! You need to use the struct Node identifier for the structure when defining it within itself. Like this:
typedef struct Node {
Ticket ticket_info;
struct Node *next;
struct Node *previous;
} Node;
I'm trying to create structs with default values. I don't know how to accomplish this because every code that I see, is about initialising, and I would it for the natural way like...
struct stuff {
int stuff_a = 1;
int stuff_b = 2...
...and so on...
};
and looking about, I found this (C++) code:
struct a{ a() : i(0), j(0) {}; INT i; INT j;}
I never saw anything like this for C. Please, help me to understand it; I think that it is very nice!
UPDATE: Wait, I'm asking about C!!!! Why changed my question? If that is not possible in C just say... I don't know C++, I didn't know that was about C++...
If you want to set a struct object in one go and you have a C99 compiler, try this:
struct stuff {
int stuff_a;
int stuff_b;
// and so on...
};
struct stuff foo;
/* ... code ... */
foo = (struct stuff){.stuff_b = 42, .stuff_a = -1000};
Otherwise, with a C89 compiler, you have to set each member one by one:
foo.stuff_b = 42;
foo.stuff_a = -1000;
Running example # ideone : http://ideone.com/1QqCB
The original line
struct a{ a() : i(0), j(0) {} INT i; INT j;}
is a syntax error in C.
As you have probably learned from the other answers, in C you can't declare a structure and initialize it's members at the same time. These are different tasks and must be done separately.
There are a few options for initializing member variables of a struct. I'll show a couple of ways below. Right now, let's assume the following struct is defined in the beginning of the file:
struct stuff {
int stuff_a;
int stuff_b;
};
Then on your main() code, imagine that you want to declare a new variable of this type:
struct stuff custom_var;
This is the moment where you must initialize the structure. Seriously, I mean you really really must! Even if you don't want to assign specific values to them, you must at least initialize them to zero. This is mandatory because the OS doesn't guarantee that it will give you a clean memory space to run your application on. Therefore, always initialize your variables to some value (usually 0), including the other default types, such as char, int, float, double, etc...
One way to initialize our struct to zero is through memset():
memset(&custom_var, 0, sizeof(struct stuff));
Another is accessing each member individually:
custom_var.stuff_a = 0;
custom_var.stuff_b = 0;
A third option, which might confuse beginners is when they see the initialization of struct members being done at the moment of the declaration:
struct stuff custom_var = { 1, 2 };
The code above is equivalent to:
struct stuff custom_var;
custom_var.stuff_a = 1;
custom_var.stuff_b = 2;
... create structs with default values ...
That is impossible in C. A type cannot have default values. Objects of any type cannot have a default value other than 0, though they can be initialized to whatever is wanted.
The definition of a struct is a definition of a type, not of an object.
What you asking is about the same thing as a way to have ints default to, say, 42.
/* WRONG CODE -- THIS DOES NOT WORK */
typedef int int42 = 42;
int42 a;
printf("%d\n", a); /* print 42 */
Or, adapting to your example
/* WRONG CODE -- THIS DOES NOT WORK */
struct stuff {
int42 stuff_a;
int65536 stuff_b;
}
struct stuff a;
printf("%d\n", a.stuff_b); /* print 65536 */
Update: This answer assumes we 're talking about C++ because the code posted in the answer is not legal C.
struct a {
a() : i(0), j(0) {} // constructor with initialization list
int i;
int j;
}
The line marked with the comment is simply the constructor for instances of struct a (reminder: structs are just like classes, except that the default member visibility is public instead of private).
The part after the : is called an initialization list: it allows you to initialize the members of the struct with values (either constants or passed as constructor parameters). Initialization of members in this list happens before the body of the constructor is entered. It is preferable to initialize members of classes and structs this way, if at all possible.
See also C++: Constructor versus initializer list in struct/class.
in C (pre C99) the following also works:
#include <stdio.h>
typedef struct
{
int a;
int b;
int c;
} HELLO;
int main()
{
HELLO a = {1,2,3};
printf("here: %d %d %d\n",a.a,a.b,a.c);
exit(1);
}
See codepad
I'm not sure quite sure what your problem is. The standard way of initialising structures in c is like this:
struct a_struct my_struct = {1, 2};
Or the more recent and safer:
struct a_struct my_struct = {.i1 = 1, .i2 = 2};
If there is more than one instance of a structure, or it needs to be re-initialised, it is useful to define a constant structure with default values then assign that.
typedef struct a_struct {
int i1;
int i2;
} sa;
static const sa default_sa = {.i1 = 1, .i2 = 2};
static sa sa1 = default_sa;
static sa sa2 = default_sa;
// obviously you can do it dynamically as well
void use_temp_sa(void)
{
sa temp_sa = default_sa;
temp_sa.i2 = 3;
do_something_with(&temp_sa);
}
// And re-initialise
void reset_sa(sa *my_sa)
{
*my_sa = default_sa;
}
Type initializer is not possible in C.
A value must be stored in the memory.
A type does not occupy memory, what occupies memory is a variable of that type.
struct stuff; is a type; it does not occupy memory
struct stuff aStuff; is a variable of that type; aStuff occupies memory
Because a type does not occupy memory, it is not possible to save values into a type.
If there is syntactic sugar to support store/initialize values into a type then there must be additional code that is inserted to assign values to every instant variables of that type (e.g: in constructor in C++). This will result in a less efficient C if this feature is available.
How often do you need to retain this default values? I think it is unlikely. You can create a function to initialize variable with the default values or just initialize every fields with the values you want. So type initializer is not fundamental thing. C is about simplicity.
Can't initialize values within a structure definition.
I'd suggest:
typedef struct {
int stuff_a;
int stuff_b;
} stuff ;
int stuffInit(int a, int b, stuff *this){
this->stuff_a = a;
this->stuff_b = b;
return 0; /*or an error code, or sometimes '*this', per taste.*/
}
int main(void){
stuff myStuff;
stuffInit(1, 2, &myStuff);
/* dynamic is more commonly seen */
stuff *dynamicStuff;
dynamicStuff = malloc(sizeof(stuff)); /* 'new' stuff */
stuffInit(0, 0, dynamicStuff);
free(dynamicStuff); /* 'delete' stuff */
return 0;
}
Before the days of Object Oriented Programming (C++), we were taught "Abstract Data Types".
The discipline said 'never access your data structures directly, always create a function for it' But this was only enforced by the programmer, instructor, or senior developer, not the language.
Eventually, the structure definition(s) and corresponding functions end up in their own file & header, linked in later, further encapsulating the design.
But those days are gone and replaced with 'Class' and 'Constructor' OOP terminology.
"It's all the same, only the names have changed" - Bon Jovi.
For my upcoming university C project, I'm requested to have modular code as C allows it. Basically, I'll have .c file and a corresponding .h file for some data structure, like a linked list, binary tree, hash table, whatever...
Using a linked list as an example, I have this:
typedef struct sLinkedList {
int value;
struct sLinkedList *next;
} List;
But this forces value to be of type int and the user using this linked list library would be forced to directly change the source code of the library. I want to avoid that, I want to avoid the need to change the library, to make the code as modular as possible.
My project may need to use a linked list for a list of integers, or maybe a list of some structure. But I'm not going to duplicate the library files/code and change the code accordingly.
How can I solve this?
Unfortunately, there is no simple way to solve this. The most common, pure C approach to this type of situation is to use a void*, and to copy the value into memory allocated by you into the pointer. This makes usage tricky, though, and is very error prone.
Another alternative no one has mentioned yet can be found in the Linux kernel's list.h generic linked list implementation. The principle is this:
/* generic definition */
struct list {
strict list *next, *prev;
};
// some more code
/* specific version */
struct intlist {
struct list list;
int i;
};
If you make struct intlist* pointers, they can safely be cast (in C) to struct list* pointers, thus allowing you to write genericized functions that operate on struct list* and have them work regardless of datatype.
The list.h implementation uses some macro trickery to support arbitrary placement of the struct list inside your specific list, but I prefer to rely on the struct-cast-to-first-member trick myself. It makes the calling code much easier to read. Granted, it disables "multiple inheritance" (assuming you consider this to be some kind of inheritance) but next(mylist) looks nicer than next(mylist, list). Plus, if you can avoid delving into offsetof hackery, you're probably going to end up in better shape.
Since this is a university project, we can't just give you the answer. Instead, I'd invite you to meditate on two C features: the void pointer (which you've likely encountered before), and the token pasting operator (which you may not have).
You can avoid this by defining value as void* value;. You can assign a pointer to any type of data this way, but the calling code is required to cast and dereference the pointer to the correct type. One way to keep track of this would be to add a short char array to the struct to note the type name.
This problem is precisely the reason why templates were developed for C++. The approach I've used once or twice in C is to have the value field be a void*, and cast the values thereto on insertion and cast them back on retrieval. This is far from type-safe, of course. For extra modularity, I might write insert_int(), get_mystruct() etc. functions for each type you use this for, and do the casting there.
You can use Void* instead of int. This allows the data to be of any type. But the user should be aware of the type of data.
For that, optionally you can have another member which represents Type. which is of enum {INT,CHAR,float...}
Unlike C++ where one can use template, void * is the de-facto C solution.
Also, you can put the elements of the linked list in a separate struct, e.g:
typedef struct sLinkedListElem {
int value; /* or "void * value" */
} ListElem;
typedef struct sLinkedList {
ListElem data;
struct sLinkedList *next;
} List;
so that the elements can be changed without affecting the link-ing code.
Here is an example of linked list utilities in C:
struct Single_List_Node
{
struct Single_List * p_next;
void * p_data;
};
struct Double_List_Node
{
struct Double_List * p_next;
struct Double_List * p_prev; // pointer to previous node
void * p_data;
};
struct Single_List_Data_Type
{
size_t size; // Number of elements in list
struct Single_List_Node * p_first_node;
struct Single_List_Node * p_last_node; // To make appending faster.
};
Some generic functions:
void Single_List_Create(struct Single_List_Data_Type * p_list)
{
if (p_list)
{
p_list->size = 0;
p_list->first_node = 0;
p_list->last_node = p_list->first_node;
}
return;
}
void Single_List_Append(struct Single_List_Data_Type * p_list,
void * p_data)
{
if (p_list)
{
struct Single_List_Node * p_new_node = malloc(sizeof(struct Single_List_Node));
if (p_new_node)
{
p_new_node->p_data = p_data;
p_new_node->p_next = 0;
if (p_list->last_node)
{
p_list->last_node->p_next = p_new_node;
}
else
{
if (p_list->first_node == 0)
{
p_list->first_node = p_new_node;
p_list->last_node = p_new_node;
}
else
{
struct Single_List_Node * p_last_node = 0;
p_last_node = p_list->first_node;
while (p_last_node->p_next)
{
p_last_node = p_last_node->p_next;
}
p_list->last_node->p_next = p_new_node;
p_list->last_node = p_new_node;
}
}
++(p_list->size);
}
}
return;
}
You can put all these functions into a single source file and the function declarations into a header file. This will allow you to use the functions with other programs and not have to recompile all the time. The void * for the pointer to data will allow you to use the list with many different data types.
(The above code comes as-is and has not been tested with any compiler. The responsibility of bug fixing is up to the user of the examples.)
Sometimes I see code like this (I hope I remember it correctly):
typedef struct st {
int a; char b;
} *stp;
While the usual pattern that I familiar with, is:
typedef struct st {
int a; char b;
} st;
So what's the advantage in the first code example?
You probably mean this:
typedef struct ST {
/* fields omitted */
} *STP;
The asterisk is at the end of the statement. This simply means "define the type STP to be a pointer to a struct of this type". The struct tag (ST) is not needed, it's only useful if you want to be able to refer to the struct type by itself, later on.
You could also have both, like so:
typedef struct {
/* fields omitted */
} ST, *STP;
This would make it possible to use ST to refer to the struct type itself, and STP for pointers to ST.
Personally I find it a very bad practice to include the asterisk in typedefs, since it tries to encode something (the fact that the type is a pointer) into the name of the type, when C already provides its own mechanism (the asterisk) to show this. It makes it very confusing and breaks the symmetry of the asterisk, which appears both in declaration and use of pointers.
It's a habit that stems from the time when typedef names and struct tagnames were in the same namespace. See http://blogs.msdn.com/oldnewthing/archive/2008/03/26/8336829.aspx
I think you are talking about :
typedef struct{
int a;
char b;
} object, *objectPointer;
This means that (new) type objectPointer is a pointer to struct (object) defined above. Its easy to declare pointers to object struct this way. For instance,
objectPointer A = (objectPointer)malloc(sizeof(object));
A->a = 2;
Now, A is a pointer to struct object and you can access its variables as described above.
In case, objectPointer was not defined,
struct object *A = (struct object *)malloc(sizeof(object));
A->a = 2;
So, I guess objectPointer is more intuitive and easy to use.
I hope that the first code would say a compiler error ,
I see no good reason for the typedef name be different from the tag name.
Now, the reason for which the tag name needs to be typedefed if you don't want to use
struct tag v;
but
tag v;
is probably an historical one. For as long as I remember, C had typedef but I don't know if it was true when struct have been introduced (handling of typedef is a nuisance in the C grammar). In the old code I've seen, using typedef for struct isn't done, and there are things like unix
struct stat;
int stat(const char*, struct stat*);
which would break with an automatic typedef. One those are introduced, changing is quite difficult (yes, C++ has automatic typedef but C++ has special wording to handle that case of overloading and it would be yet another complication).
In the question Why should we typedef a struct so often in C?, unwind answered that:
In this latter case, you cannot return
the Point by value, since its
declaration is hidden from users of
the header file. This is a technique
used widely in GTK+, for instance.
How is declaration hiding accomplished? Why can't I return the Point by value?
ADD:
I understood why I can't return the struct by value, but, is still hard to see why i can't deference this point in my function. i.e. If my struct have member named y, why i can't do it?
pointer_to_struct->y = some_value;
Why should I use methods to do it? (Like Gtk+)
Thanks guys, and sorry for my bad english again.
Have a look at this example of a library, using a public header file, a private header file and an implementation file.
In file public.h:
struct Point;
struct Point* getSomePoint();
In file private.h:
struct Point
{
int x;
int y;
}
In file private.c:
struct Point* getSomePoint()
{
/* ... */
}
If you compile these three files into a library, you only give public.h and the library object file to the consumer of the library.
getSomePoint has to return a pointer to Point, because public.h does not define the size of Point, only that is a struct and that it exists. Consumers of the library can use pointers to Point, but can not access the members or copy it around, because they do not know the size of the structure.
Regarding your further question:
You can not dereference because the program using the library does only have the information from private.h, that does not contain the member declarations. It therefore can not access the members of the point structure.
You can see this as the encapsulation feature of C, just like you would declare the data members of a C++ class as private.
What he means is that you cannot return the struct by-value in the header, because for that, the struct must be completely declared. But that happens in the C file (the declaration that makes X a complete type is "hidden" in the C file, and not exposed into the header), in his example. The following declares only an incomplete type, if that's the first declaration of the struct
struct X;
Then, you can declare the function
struct X f(void);
But you cannot define the function, because you cannot create a variable of that type, and much less so return it (its size is not known).
struct X f(void) { // <- error here
// ...
}
The error happens because "x" is still incomplete. Now, if you only include the header with the incomplete declaration in it, then you cannot call that function, because the expression of the function call would yield an incomplete type, which is forbidden to happen.
If you were to provide a declaration of the complete type struct X in between, it would be valid
struct X;
struct X f(void);
// ...
struct X { int data; };
struct X f(void) { // valid now: struct X is a complete type
// ...
}
This would apply to the way using typedef too: They both name the same, (possibly incomplete) type. One time using an ordinary identifier X, and another time using a tag struct X.
In the header file:
typedef struct _point * Point;
After the compiler sees this it knows:
There is a struct called _point.
There is a pointer type Point that can refer to a struct _point.
The compiler does not know:
What the struct _point looks like.
What members struct _point contains.
How big struct _point is.
Not only does the compiler not know it - we as programmers don't know it either. This means we can't write code that depends on those properties of struct _point, which means that our code may be more portable.
Given the above code, you can write functions like:
Point f() {
....
}
because Point is a pointer and struct pointers are all the same size and the compiler doesn't need to know anything else about them. But you can't write a function that returns by value:
struct _point f() {
....
}
because the compiler does not know anything about struct _point, specifically its size, which it needs in order to construct the return value.
Thus, we can only refer to struct _point via the Point type, which is really a pointer. This is why Standard C has types like FILE, which can only be accessed via a pointer - you can't create a FILE structure instance in your code.
Old question, better answer:
In Header File:
typedef struct _Point Point;
In C File:
struct _Point
{
int X;
int Y;
};
What that post means is: If you see the header
typedef struct _Point Point;
Point * point_new(int x, int y);
then you don't know the implementation details of Point.
As an alternative to using opaque pointers (as others have mentioned), you can instead return an opaque bag of bytes if you want to avoid using heap memory:
// In public.h:
struct Point
{
uint8_t data[SIZEOF_POINT]; // make sure this size is correct!
};
void MakePoint(struct Point *p);
// In private.h:
struct Point
{
int x, y, z;
};
void MakePoint(struct Point *p);
// In private.c:
void MakePoint(struct Point *p)
{
p->x = 1;
p->y = 2;
p->z = 3;
}
Then, you can create instances of the struct on the stack in client code, but the client doesn't know what's in it -- all it knows is that it's a blob of bytes with a given size. Of course, it can still access the data if it can guess the offsets and data types of the members, but then again you have the same problem with opaque pointers (though clients don't know the object size in that case).
For example, the various structs used in the pthreads library use structs of opaque bytes for types like pthread_t, pthread_cond_t, etc. -- you can still create instances of those on the stack (and you usually do), but you have no idea what's in them. Just take a peek into your /usr/include/pthreads.h and the various files it includes.