I was recently reading about ways to create something that resembles c++ objects, but in C, and I came across some pretty good examples. However, there was this single piece of code that had me thinking for hours, since it was the first time I saw this kind of syntax, and I didn't find anything like it on Google...
The block itself is this one:
struct stack {
struct stack_type * my_type;
// Put the stuff that you put after private: here
};
struct stack_type {
void (* construct)(struct stack * this); // This takes uninitialized memory
struct stack * (* operator_new)(); // This allocates a new struct, passes it to construct, and then returns it
void (*push)(struct stack * this, thing * t); // Pushing t onto this stack
thing * (*pop)(struct stack * this); // Pops the top thing off the stack and returns it
int this_is_here_as_an_example_only;
}Stack = {
.construct = stack_construct,
.operator_new = stack_operator_new,
.push = stack_push,
.pop = stack_pop
};
Assuming all the functions being set to the pointers are defined somewhere else, my doubts are the following:
1) Why does the point ( '.' ) mean, or whats its purpose when initializing the function pointers? (example: .construct = stack_construct )
2) why is there an equal sign after 'Stack' at the end of the struct definition, and why is there something other than a ';' ( in this case the word 'Stack' ), given the fact that there is no typedef at the beginning?
I assume it has something to do with initialization (like a constructor, I don't know), but it is the first time I see a struct = {...,...,...} in the definition. I've seen that when you initialize a struct like in the following example:
typedef struct s{
int a;
char b;
}struc;
void main(){
struc my_struct={12,'z'};
}
But this is not in the main declaration of the struct, and still, there are no '=' within the {}, unlike the first example, where it showed something like...
struc my_struct={ a = 12,
b = 'z'};
3) This is a minor doubt, meaning, I'm much more interested in the first two. Anyway, here it goes...
At the beginning of the first code, it says something like '// Put the stuff that you put after private: here'. Why is that? how would that make them private?
That is all, I would appreciate anything, this had me thinking for hours! Thanks in advance, have a great day!
1) Don't worry about the members being functions, it's just this:
What does dot (.) mean in a struct initializer?
2) In
struct S {int i;}
s = {0};
the first line names a type that can be used to declare and initilize a variable.
It is really equivalent with something like
double d = 1;
where you replace double with struct S {int i;}, replace s with d, and replace 1 with the initializer for a struct, {0}. Now combine this with the dot syntax.
It just has the side effect of also defining struct S.
Update:
Regarding 3), I do not think that with private they refer to an implementation of access control, but rather refer to the fact that in C++, you would usually list the data members in the private section of the class, so I understand this as instructions to add the data members after the type identifying element.
Related
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.
I'm really new to C programming and I'm still trying to understand the concept of using pointers and using typedef structs.
I have this code snippet below that I need to use in a program:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
I'm not exactly sure what this does - to me it seems similar as using interfaces in Objective-C, but I don't think that's the case.
And then I have this line
pStudentRecord* g_ppRecords;
I basically need to add several pStudentRecord to g_ppRecords based on a number. I understand how to create and allocate memory for an object of type pStudentRecord, but I'm not sure how to actually add multiple objects to g_ppRecords.
defines a pointer to the struct described within the curly bracers, here is a simpler example
typedef struct {
int x;
int y;
}Point,* pPoint;
int main(void) {
Point point = {4,5};
pPoint point_ptr = &point;
printf("%d - %d\n",point.x,point_ptr->x);
pPoint second_point_ptr = malloc(sizeof(Point));
second_point_ptr->x = 5;
free(second_point_ptr);
}
The first declares an unnamed struct, and a type pStudentRecord that is a pointer to it. The second declares g_ppRecords to be a pointer to a pStudentRecord. In other words, a pointer to a pointer to a struct.
It's probably easier to think of the second as an "array of pointers". As such, g_ppRecords[0] may point to a pStudentRecord and g_ppRecords[1] to another one. (Which, in turn, point to a record struct.)
In order to add to it, you will need to know how it stores the pointers, that is, how one might tell how many pointers are stored in it. There either is a size somewhere, which for size N, means at least N * sizeof(pStudentRecord*) of memory is allocated, and g_ppRecords[0] through g_ppRecords[N-1] hold the N items. Or, it's NULL terminated, which for size N, means at least (N+1) * sizeof(pStudentRecord*) of memory is allocated and g_ppRecords[0] through g_ppRecords[N-1] hold the N items, and g_ppRecords[N] holds NULL, marking the end of the string.
After this, it should be straightforward to create or add to a g_ppRecords.
A struct is a compound data type, meaning that it's a variable which contains other variables. You're familiar with Objective C, so you might think of it as being a tiny bit like a 'data only' class; that is, a class with no methods. It's a way to store related information together that you can pass around as a single unit.
Typedef is a way for you to name your own data types as synonyms for the built-in types in C. It makes code more readable and allows the compiler to catch more errors (you're effectively teaching the compiler more about your program's intent.) The classic example is
typedef int BOOL;
(There's no built-in BOOL type in older ANSI C.)
This means you can now do things like:
BOOL state = 1;
and declare functions that take BOOL parameters, then have the compiler make sure you're passing BOOLs even though they're really just ints:
void flipSwitch(BOOL isOn); /* function declaration */
...
int value = 0;
BOOL boolValue = 1;
flipSwitch(value); /* Compiler will error here */
flipSwitch(boolValue); /* But this is OK */
So your typedef above is creating a synonym for a student record struct, so you can pass around student records without having to call them struct StudentRecord every time. It makes for cleaner and more readable code. Except that there's more to it here, in your example. What I've just described is:
typedef struct {
char * firstName;
char * lastName;
int id;
float mark;
} StudentRecord;
You can now do things like:
StudentRecord aStudent = { "Angus\n", "Young\n", 1, 4.0 };
or
void writeToParents(StudentRecord student) {
...
}
But you've got a * after the typedef. That's because you want to typedef a data type which holds a pointer to a StudentRecord, not typedef the StudentRecord itself. Eh? Read on...
You need this pointer to StudentRecord because if you want to pass StudentRecords around and be able to modify their member variables, you need to pass around pointers to them, not the variables themselves. typedefs are great for this because, again, the compiler can catch subtle errors. Above we made writeToParents which just reads the contents of the StudentRecord. Say we want to change their grade; we can't set up a function with a simple StudentRecord parameter because we can't change the members directly. So, we need a pointer:
void changeGrade(StudentRecord *student, float newGrade) {
student->mark = newGrade;
}
Easy to see that you might miss the *, so instead, typedef a pointer type for StudentRecord and the compiler will help:
typedef struct { /* as above */ } *PStudentRecord;
Now:
void changeGrade(PStudentRecord student, float newGrade) {
student->mark = newGrade;
}
It's more common to declare both at the same time:
typedef struct {
/* Members */
} StudentRecord, *PStudentRecord;
This gives you both the plain struct typedef and a pointer typedef too.
What's a pointer, then? A variable which holds the address in memory of another variable. Sounds simple; it is, on the face of it, but it gets very subtle and involved very quickly. Try this tutorial
This defines the name of a pointer to the structure but not a name for the structure itself.
Try changing to:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
} StudentRecord;
StudentRecord foo;
StudentRecord *pfoo = &foo;
This question already has answers here:
Understanding typedef with struct [duplicate]
(6 answers)
Closed 5 years ago.
I have few questions connected with struct and typedef, there is piece of code and I have marked some places where I'm not sure if the syntax is correct. I use Eclipse editor and it shows me when there is problem in compilation. I just don't understand why is sometimes keyword struct needed and sometimes not. I may have also some mistakes of using this keyword. So plese help me to understand it.
let's have struct
typedef struct player
{
char *name;
int gameId;
int points;
int socketfd; //socket descriptor of player
int state;
} player_struct;
lets have another struct
#define PLAYERSLEN 2
typedef struct game{
struct player_struct *players[PLAYERSLEN]; //PLACE1
//some code
} game_struct;
let's have function
player_struct *create_player() //PLACE2
{
player_struct *player; //PLACE3
//alokace pameti
player = (player_struct *) malloc(sizeof(player_struct)); //PLACE4
//PLACE5
player->gameId = -1;
player->points = 0;
player->state = 0;
return player;
}
let's have function? In fact what does this definition mean?
void *( player_struct *player) //PLACE6
{
//some code
}
Questions references:
PLACE1 - is this correct? why can't I use just player_struct *players[PLAYERSLEN]; ??
PLACE2 - it looks like there is not needed struct before player_struct , is it correct? why?
PLACE3 - it looks like there is struct also not needed, is it correct? why?
PLACE4 - it looks like there is struct also not needed, is it correct? why?
PLACE4 & PLACE5 I may should handle errors there, cause there is malloc so I should probably put all the line with PLACE4 to if and if the malloc fails I should put at PLACE 5 free(player). Am I right?
PLACE6 what could have mean this function or whatever it is? The code inside brackets which is not included here should delete the player .. I just don't understand the syntax of wrote function - what does it mean?
PLACE6 - again similar as previous why is not necessary put the keyword struct before player_struct at this line? is it correct?
Really thanks you for your time.
You're doing two things in the initial definition:
You're defining the structure with the type name struct player.
You're creating a typedef called player_struct, which is just an alias for struct player.
As such, either struct player or player_struct is correct (and more-or-less equivalent), but struct player_struct refers to a completely separate type, and is probably incorrect unless you're trying to confuse people.
Now, handling your six cases in order:
PLACE1: As noted above, this code is actually wrong as it stands.
PLACE2, PLACE3, PLACE4: All correct; see above for an explanation.
PLACE5: Yes, you should probably check that player != NULL here just to be sure.
PLACE6: Again, this is correct, and the reason why is above. I'm not sure what void *(...) is supposed to be, though -- if * is actually a function name then it's probably fine though.
It's because the labels are in two separate namespaces (yes, even in C). There's a special namespace for structs.
I like to declare the label in both namespaces, using this:
typedef struct mon_struct {
int a;
} mon_struct;
then you can use either/both struct mon_struct mon = ... or just mon_struct mon = ....
Update
If you want to use just one label, then you can use one of the following:
struct mon_struct { int a; };
// requires namespace resolution using struct tag:
void f(struct mon_struct p);
// -= OR =-
// slightly awkward declaration
typedef struct { int a; } mon_struct;
// but the type exists in the global namespace,
// so we don't need to use the struct tag:
void f(mon_struct p);
but this becomes messy if you are using the struct in both C and C++, particularly when the declaration or implementations move between C and C++ translations without proper guarding (extern "C" { ...stuff... }).
so you might opt to declare it in both namespaces to minimise breakage:
typedef struct mon_struct { int a; } mon_struct;
void f(struct mon_struct p); // << ok
void f2(mon_struct p); // << ok
No. player_struct is a typedef for struct player. You don't need the struct keyword in this case.
Correct. You created a type definition called player_struct which means struct player.
Same reason as 2.
Same reason as 2 & 3.
Yes, you should check to see if malloc() returns NULL. In addition, don't cast the return value from malloc(). Doing so can hide #include errors.
That's not a valid function definition. You don't need struct because of the typedef - same as above.
You may find this all makes more sense if you remove the words typedef, player_struct, and game_struct from your code entirely. Then once you get used to how that all works, you can reintroduce the typedefs and maybe cut down on some typing. As a quick example, you can break down your first definition into its components:
struct player
{
char *name;
int gameId;
int points;
int socketfd; //socket descriptor of player
int state;
};
typedef struct player player_struct;
Maybe that will help you make sense of it?
You don't need struct in PLACE1... as long the definition of player_struct is known, ie, declared before it, or from a .h before it.
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.
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).