c structures that contain function pointers - c

I declare all my structures using the following macro..
#define structure typedef struct
with this I declare a structure , for example
structure
{
int foo;
int(*proc)(void*);
}
_myobject;
the member proc , really received the argument which is a pointer
to the structure it belongs to ..
e.g.
myobj.proc(&myobj);
My question is , how can I declare the member proc with the type being
passed to it as a structure , and not a void * .. I know it doesn't make
a difference, this is only for aesthetics, as I have spent a lot of time
keeping my code clean..
structure
{
int foo
int(*foo)(_myobject*);
}
_myobject;
produces:
error: expected ':', ',', ';', '}' or '__attribute__' before 'int'|

You're attempting to refer to your struct recursively, which doesn't play nice with typedefs. One of the following should do:
typedef struct _myobject _myobject;
struct _myobject {
int foo;
int (*proc)(_myobject*);
};
...
typedef struct _myobject {
int foo;
int (*proc)(struct _myobject*);
} _myobject;
edit: If you want to continue using structure as much as possible (though really, other than for consistency with the existing code, I'm not sure why you would want to), you could do:
structure _myobject _myobject;
struct _myobject {
int foo;
int (*proc)(_myobject*);
};
...
structure _myobject {
int foo;
int (*proc)(struct _myobject*);
} _myobject;
Though both of these will require use of the struct identifier, if you wanted to avoid that.

You can change the macro a little:
#define structure(x,y) typedef struct x y x
structure (_myobject,
{
int foo;
int(*proc)(struct _myobject*);
}
);
which looks bad to me. Another way to do this is:
#define structure typedef struct
structure _myobject
{
int foo;
int(*proc)(struct _myobject*);
}
_myobject;

Related

C access enum from struct

My problem is that car_name_str could not be resolved. Why is it not callable and I want to keep the code structure?
I want to keep the structure as struct with union and enum (different datatypes).
Template: How can mixed data types (int, float, char, etc) be stored in an array?
//car_union.h
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
//fill_car.c
#include "car_union.h"
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str; //-> because pointer but doesnt work
Car_data[0][0]->value->car_name= "land rover";
Car_data[0][1]->type = car_cost_float; //doesnt work
Car_data[0][1]->value->car_cost= 45000;
Just remove the [30][3] from the type def, like this
#include <stdio.h>
//car_union.h
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex;
extern Car_data_ex *Car_data[30][3];
int main() {
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str; //-> because pointer but doesnt work
Car_data[0][0]->value.car_name= "land rover";
Car_data[0][1]->type = car_cost_float; //doesnt work
Car_data[0][1]->value.car_cost= 45000;
}
Regardless of what's in your struct, when you do
typedef struct Car_dataStructTag{
//...
}Car_data_ex[30][3];
(I've tagged the struct so it can be referred to by struct Car_dataStructTag),
then Car_data_ex is a type alias resolving to struct Car_dataStructTag [30][3]
which means
extern Car_data_ex *Car_data[30][3];
is fully equivalent to
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];
which means Car_data[x][y] is a pointer to a two-dimensional array of struct Car_dataStructTag,
which is definitely not something you can apply -> to.
Try:
typedef struct Car_dataStructTag{
//...
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];
in a compiler -- it gets accepted, confirming the declaration equivalence.
Running into situations such as this one is why it's generally considered ill-advisable to typedef arrays or pointers.
You have over complexified everything.
A typedef is just to give an alias to a (complex) type. Here the type is a struct containing an enum and an union. So it should be:
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex;
Next, using an array of pointers can make sense, but provided each pointer in the array does point to a true object. Here you only want a plain (2D) array:
Car_data_ex Car_data[30][3];
Once this has been done, you can write with no error or warning:
Car_data[0][0].type = car_name_str;
Car_data[0][0].value.car_name= "land rover";
Car_data[0][1].type = car_cost_float;
Car_data[0][1].value.car_cost= 45000;
And you should avoid extern Car_data_ex Car_data[30][3];. It declares a global array, that will have to be defined in one single compilation unit (.c file). Here again, it can make sense, but IMHO it is a rather advanced feature that can be hard to correctly use. And nothing in the shown code lets think that is is required...

typedef struct but keep new type namespaced under keyword 'struct'

How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?
example:
struct foo {
int x;
};
typedef struct foo struct bar;
int main(void) {
struct bar bar;
bar.x = 10;
return 0;
}
but this doesn't work obviously.
Here are the errors if anyone is curious:
main.c:5:20: error: two or more data types in declaration specifiers
typedef struct foo struct bar;
^
main.c:5:27: warning: useless storage class specifier in empty declaration
typedef struct foo struct bar;
^
main.c: In function 'main':
main.c:9:13: error: storage size of 'bar' isn't known
struct bar bar;
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?
So, it seems that you want to define a structure alias for another structure type.
This is not possible with typedef as it creates a single word alias. The new alias can't be consisted of multiple white space separated words.
But you can use a single name like struct_bar with struct implemented inside of the name to show that bar is a structure.
#include <stdio.h>
struct foo {
int x;
};
typedef struct foo struct_bar;
int main(void) {
struct_bar bar;
bar.x = 10;
return 0;
}
How can I typedef a struct but still keep the new type namespaced under the keyword 'struct'?.
You cannot. A namespace is a declarative region that provides a scope to the identifiers (names of the types, function, variables etc) inside it. The concept of Namespace as it is defined within C++, is not inherent in C.
So, if you are okay with minor changes in your requirements, instead of doing something unnatural, use a simple typedef:
Instead of this:
struct foo {
int x;
};
do this:
typedef struct {
int x;
}foo;
Then this will work:
typedef foo bar;
int main(void )
{
bar b;
b.x = 10;
return 0;
}
Note: Although namespaces are not inherent in in C, as they are in C++, there are some interpretations eg: as discussed here, that argue the point.
C doesn't have any type of support for namespaces (at least not in the sense that C++ does).
When you create a typedef, the new type name is a single identifier, not multiple words. So struct bar can't be an alias for another type. You would have to call it bar or some other one-word name.
You can't. This isn't how it works.
You cannot "create" a type whose name is more than one word, nor can you refer to a type alias using the keyword struct.
The purpose of writing struct, in this context, is to refer to a struct type by a name that wasn't introduced as an alias. The keyword is there to say that that's what you want to do. But it's not part of the name; it cannot be part of the name.
Fortunately, there's no reason to need or even want this.
I found a solution that works for cygwin:
struct foo {
int x;
};
struct bar {
struct foo;
};

Visual C 2012: I am getting weird errors. Code Segment and Error provided

I am writing a game in C. But I keep getting a number of errors. One prominent one is this. "Illegal Identifier: X" where X is the type of a variable inside a structure. An instance, Illegal Identifier: MapItem, is caused by the following code
typedef struct MapItem{
int item;
int count;
};
typedef struct MapTile{
MapItem item;
int x;
int y;
int tile;
Direction dir;
int drop;
};
The error is attached to the first line inside the MapTile struct. I would like to know why this error is occurring, and how to fix it.
The code segment was taken, in exact order, from map.h. Direction is an enum declared earlier in the same header.
Thank you all for answering. However, I did receive the answer I needed 4 hours ago.
Your typedef are incorrect. The syntax is:
typedef type typealias ;
So:
typedef struct
{
int item;
int count;
} MapItem;
typedef struct
{
MapItem item;
int x;
int y;
int tile;
Direction dir;
int drop;
} MapTile;
Note that types being aliased here are anonymous structs, the struct-tag is only required for self-referencing structs.
typedef is used to create an alias to another type (existing or defined in the same typedef statement).
Its general format is:
typedef existing_or_new_type alias;
The aliased type in your typedef is the new struct MapItem defined in the typedef statement but the alias is missing. This is the cause of the error.
You can use:
typedef struct MapItem {
int item;
int count;
} MapItem;
This statement declares the new type struct MapItem (the struct keyword is part of the type name) and the new type MapItem that is an alias of struct MapItem. This means that everywhere you can or have to use struct MapItem you can use MapItem instead.
If this seems confusing, you can use different names for the struct type and its alias. Or you can omit the name from the struct definition at all:
typedef struct {
int item;
int count;
} MapItem;
This way, MapItem is the name of an anonymous struct type and it is the only way to declare variables of this type.

Nested struct in C issue

I have a struct declaration in C that looks something like this:
static struct {
int a;
int b;
} myStruct[10];
I want to declare a struct member variable inside myStruct, so I try to add this:
static struct {
int c;
int d;
struct myStruct[10] s;
} myNestedStruct[100];
I'm getting a bunch of errors i.e. syntax error before or at: [ and
syntax requires ";" after last struct/union member. What would the better way to implement the nested structs be?
EDIT: My code now looks like this:
static struct {
int a;
int b;
} myStruct[10];
static struct {
int c;
int d;
struct myStruct s[10];
} myNestedStruct[100];
However I'm getting an error: incomplete struct/union/enum myStruct: s
You need to declare myStruct first before using it as a struct type.
struct myStruct {
int a;
int b;
};
static struct {
int c;
int d;
struct myStruct s[10];
} myNestedStruct[100];
This creates a variable called myNestedStruct which is an array of 100 structs, each containing two ints and an array of 10 mystructs.
When you write code like
struct { ... } Foo;, it's not declaring a type named Foo but a variable. Its type is an anonymous struct corresponding to what you put in the curly braces. If you want to declare a type, write struct Foo { ... };.
That's where your error is coming from -- myStruct is not a type name, so when you write struct myStruct in the definition of myNestedStruct the compiler thinks you're about to define a struct by that name. But then it encounters an [ which shouldn't be the next token in a struct declaration ever so it tells you can't make sense of the code.

What's the syntactically proper way to declare a C struct?

I've seen C structs declared several different ways before. Why is that and what, if anything, does each do different?
For example:
struct foo {
short a;
int b;
float c;
};
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
int main (int argc, char const *argv[])
{
struct foo a;
bar b;
baz c;
return 0;
}
Well, the obvious difference is demonstrated in your main:
struct foo a;
bar b;
baz c;
The first declaration is of an un-typedefed struct and needs the struct keyword to use. The second is of a typedefed anonymous struct, and so we use the typedef name. The third combines both the first and the second: your example uses baz (which is conveniently short) but could just as easily use struct _baz to the same effect.
Update: larsmans' answer mentions a more common case where you have to use at least struct x { } to make a linked list. The second case wouldn't be possible here (unless you abandon sanity and use a void * instead) because the struct is anonymous, and the typedef doesn't happen until the struct is defined, giving you no way to make a (type-safe) pointer to the struct type itself. The first version works fine for this use, but the third is generally preferred in my experience. Give him some rep for that.
A more subtle difference is in namespace placement. In C, struct tags are placed in a separate namespace from other names, but typedef names aren't. So the following is legal:
struct test {
// contents
};
struct test *test() {
// contents
}
But the following is not, because it would be ambiguous what the name test is:
typedef struct {
// contents
} test;
test *test() {
// contents
}
typedef makes the name shorter (always a plus), but it puts it in the same namespace as your variables and functions. Usually this isn't an issue, but it is a subtle difference beyond the simple shortening.
It's largely a matter of personal preference. I like to give new types a name starting with a capital letter and omit the struct, so I usually write typedef struct { ... } Foo. That means I cannot then write struct Foo.
The exception is when a struct contains a pointer to its own type, e.g.
typedef struct Node {
// ...
struct Node *next;
} Node;
In this case you need to also declare the struct Node type, since the typedef is not in scope within the struct definition. Note that both names may be the same (I'm not sure where the underscore convention originated, but I guess older C compilers couldn't handle typedef struct X X;).
All your uses are syntactically correct. I prefer the following usage
/* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
short a;
int b;
foo* next;
};
Observe that this easily allows to use the typedef already inside the declaration of the struct itself, and that even for struct that reference each other mutually.
The confusion comes about because some of the declarations are in fact declaring up to three C constructs. You need to keep in mind the difference between:
A typedef declaration,
A struct definition, and
A struct declaration.
They are all very different C constructs. They all do different things; but you can combine them into the one compound construct, if you want to.
Let's look at each declaration in turn.
struct foo {
short a;
int b;
float c;
};
Here we are using the most basic struct definition syntax. We are defining a C type and give it the name foo in the tag namespace. It can later be used to declare variables of that type using the following syntax:
struct foo myFoo; // Declare a struct variable of type foo.
This next declaration gives the type another name (alias) in the global namespace. Let's break it down into its components using the previous basic declaration.
typedef foo bar; // Declare bar as a variable type, the alias of foo.
bar myBar; // No need for the "struct" keyword
Now just replace "foo" with the the struct's definition and voila!
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
The above syntax is equivalent to the following sequence of declarations.
struct _baz {
short a;
int b;
float c;
}
typedef _baz baz; // Declare baz as an alias for _baz.
baz myBaz; // Is the same as: struct _baz myBaz;

Resources