I have the following c code:
struct {
short s;
int n;
} variableName;
I want to write a function to capture this variable like so
void func(MyStruct* var){
//do stuff
}
func(&variableName);
I would like to do this without providing a definition for the struct. Is there a way to capture variableName?
No, you can't pass an "anonymous" struct into a function in C. You could of course define your function to accept the arguments individually:
void func(short s, int n) { ... }
Or you can define the MyStruct structure in a place that both the function and the calling code has visibility to. Note that the whole struct is passed by value (copy) when you do that, which may be the behavior you want here (or may not be).
You may be looking for something more like a "dictionary" or "associative array" or "hash" type that many other languages provide, with arbitrary key value pairs in it. Pure C does not have a facility for this; the compiler wants to know the layout of a structure in advance.
(I'm not sure if you might be asking about a slightly more esoteric idea, which is hiding the composition of a structure and passing around an "opaque handle" out of and into an API. There are ways to structure that in C, but please say so if that's what you're talking about.)
Completely overlooked "I would like to do this without providing a definition for the struct. Is there a way to capture variableName?" in the OP, unless it was edited after. The question makes less sense now, but heres how you could normally pass a struct to a function for future readers.
#include <stdio.h>
struct StructName{
short s;
int n;
};
void func(struct StructName struct_var){
printf("Param values are: %4X %4X\n", struct_var.s & 0xFFFF, struct_var.n & 0xFFFF);
}
int main(){
struct StructName struct_var;
struct_var.s = 0xDEAD;
struct_var.n = 0xBEEF;
func(struct_var);
}
//It looks like you are trying to use the definition as a variable. Here the definition is StructName and the variable is struct_var.
this sample code outputs:
Param values are: DEAD BEEF
If you use clang or gcc, you may be able to use typeof:
struct foo {
struct {
int i;
} anon;
} foo;
void do_something(typeof(foo.anon)* member) {
member->i = 1;
}
If there is no global instance of your type, you may be able to use typeof((struct foo){}.anon).
This comes with a lot of downsides. The most obvious ones are that:
it's not standard, and it ties you to clang/gcc
it's pretty darn ugly
it might not behave as you expect anyway
For instance, structurally-equivalent anonymous types do not have the same type, so in something like this:
struct foo {
struct {
int i;
} anon1;
struct {
int i;
} anon2;
} foo;
anon1 and anon2 both have a different type, meaning that typeof one of them cannot be used to refer to both.
In the long run, you will almost certainly find that it's worth naming the structures, especially if you use them as function arguments. For instance, if you want to make your variable available from a header, I think that you'll have to work pretty hard to keep it anonymous.
Although it's not particularly pretty and not compatible with C++, C puts the name of nested declarations in the global namespace, so this is portable and it's not a very big code change to front-load:
struct {
struct not_anon {
int i;
} anon;
} foo;
void do_something(struct not_anon* member) {
member->i = 1;
}
Related
I want to write data to an array of structures. The structure itself is declared and defined inside main(). I have 3 functions that need to write, process and read the data from the array.
All I could achieve was creating a global struct declaration and then passing pointers to them.
Is it possible without making the structure declaration global?
The relevant code is posted below.
This is my struct declaration outside of main()
struct date
{
int d;
int m;
int y;
};
struct stud
{
int roll;
char name[30];
struct date dob;
int P;
int C;
int M;
float PCM;
char flag_in;
char flag_pro;
};
These are the function defintions.
void getdata(struct stud *S)
{
scanf("%d", &(S->roll));
scanf("%s", (S->name));
//Similarly for dob, p, c, m
(S->flag_in)='1';
return;
}
void process(struct stud *S)
{
if(S->flag_in=='1')
{
S->PCM=(S->P + S->C + S->M)/3;
S->flag_pro='1';
}
}
void display(struct stud *S)
{
for(int x=0; x<10; x++)
if(S[x].flag_in=='1')
{
//printing the data to the console output
}
}
These are the function calls:
getdata(&S[i]);
process(&S[x]);
display(S);
It's entirely valid to not want to expose other parts of your program to the internal structure of a type.
C is extremely well placed to do this with considerable elegance.
Call this X.h
//Declaration of X as pointing to an incomplete struct XS.
//This says there's such a thing as a struct XS but not how it is laid out or even how big it is.
//It also says X is a short-hand for a pointer to a mysterious XS structure.
typedef struct XS* X;
//Creates an X and returns a pointer to it. Remember to call destroyX(.) exactly once - later.
X createX(void);
//Does something with X and returns some number.
int doXThing(X x);
//Destroys an X. Must be called exactly once for each return value from createX().
void destroyX(X x);
This is prog.c (containing your main(.) function).
#include <stdlib.h>
#include <stdio.h>
#include "X.h"
//Now we actually define that mysterious structure.
//Other translation units will not see this.
struct XS {
int v;
} ;
//Here we have size and layout so we can actually implement it.
X createX(void){
X x=malloc(sizeof(struct XS));//Explicit allocation of 'implementation struct'.
if(x==NULL){
return NULL;//malloc(.) failed.
}
x->v=0;
return x;
}
int doXThing(X x){
return (x->v)++;
}
void destroyX(X x){
free(x);
}
int main(void) {
X x=createX();
printf("%d\n",doXThing(x));
printf("%d\n",doXThing(x));
printf("%d\n",doXThing(x));
destroyX(x);
return 0;
}
Notice that the other modules using #include "X.h" don't see the layout of the structures.
The upside is the implementation can change normally without recompilation - just re-linking.
The downside is that without access to the size and layout of X those 'using' modules need to delegate all the work to a module that does!
That means all Xs have to come of the free-store (or a static pool inside the implementing module..).
This model is really rather common and quite powerful as it allows for complete abstraction and data hiding.
If you're willing to do a load of casting you don't even need to 'reveal' the name XS.
typedef XSHandle* X;
Or even
typedef unsigned short* X; //Little used type... Illegal but works on most platforms - check your documentation of use char (bare, signed or unsigned).
But don't get led into:
typedef void* X;
In C. void* is so promiscuous in its casting you will get into trouble!
C++ however behaves far better about that.
PS: It's not normal to put the implementation in the same translation unit as main(.).
It's not wrong in a small project but it's not normal to get into quite so much abstraction in a small project.
PPS: A stated this method provides for a very high degree of OO programming. It may be of interest that Stroustrup made documented design decisions to NOT do this for all classes in C++ because it has a fixed and unavoidable overhead and he gave himself a 'zero-overhead principle' and wanted to provide a way of 'mixing' abstraction with direct access to object layout (allocation as local variable, direct access to members, inline functions,...).
I think he made the right decision as a language level decision for the intended use of C++. That doesn't make it a bad design pattern where appropriate.
What you could do is declare the struct inside the main. and pass the pointer when the functions are called:
//this code is inside main
struct stud arr[10]; // create an array for the struct
display(arr); //pass the pointer to function
since the main is called before the functions the data will not be deleted and will exist on the processing of other functions which can pass the pointer between them.
Although I suggest not to use this method if the functions are not for one purpose (change value, print, etc...). If the data struct is used as global declare it as global.
I have the impression that you are not clear on the difference between the definition of a struct type and an instance of that type.
To be able to work with a struct variable, your functions have to see the full type declaration, such that the compiler knows how the variable is structured and to access the different fields. But there is no need that they see the variable declaration as such. The variable can be accessed without problems through a pointer that you pass as argument.
If you have your structure within the main() then the scope of this structure is local to main()
Since structures are user-defined data-types it can't used as you try because this new type is just visible within the main()
So the functions which you have defined will not have visibility of the structure.
So in order to handle this the structure should be made global.
So a binary answer to your question
Is it possible without making the structure declaration global?
is NO
Is it possible without making the structure declaration global?
No, any functions needs a struct's definition to be visible (globally) for it to be useable. Otherwise, from the function's viewpoint, the invisible struct would be an undefined identifier.
Local structs will not be visible anywhere outside the function.
The more important question would be what do you save in making it local as opposed to global? One thing that comes to my mind is that compilation time might be faster since if declared global in a header where lot of TUs see it unnecessarily.
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.
Given this simple C code:
struct {
struct a {
int foo;
};
struct b {
char *bar;
};
} s;
I am wondering whether there is a way to access a variable in one of the nested structures in a more compact way than s.a.foo = 5, for instance.
First, notice that your example is not standard C89 (but it is acceptable by some compilers when you ask for some language extensions. With GCC you'll need to extend the accepted C dialect with the -fms-extensions flag to the compiler). You are using unnamed fields. A more standard way of coding would be:
struct a {
int foo;
};
struct b {
char* bar;
};
struct {
struct a aa;
struct b bb;
} s;
Back to your question, no, there is no other way. However, you might use preprocessor macros, whcih could help. For instance, assuming the above declarations, you could
#define afoo aa.foo
#define bbar bb.bar
and then you can code s.afoo instead of s.aa.foo
You might also define macros like
#define AFOO(X) (X).aa.foo
and then code AFOO(s)
Using such preprocessor macros does have some annoyance: with my example, you cannot declare anymore a variable (or formal argument, or field, or function) named afoo
But I am not sure you should bother. My personal advice & habit is to give longer and often unique names to fields (and also to name struct a_st my struct-ures). Take advantage of the auto-completion abilities of your editor. Don't forget that your code is more often read than written, so use meaningful names in it.
There is not. You have to specify the path the the memory address you wish to reference.
You can't cast structs directly, but you can cast pointers to structs. So if you have this stuct:
typedef struct {
struct {
int foo;
} a;
struct {
char bar;
} b;
} s;
You can create a struct like this:
typedef struct {
int foo;
char bar;
} sa;
Now when you create the struct, stash a pointer to it:
s myS;
myS.a.foo = 123;
myS.b.bar = 10;
sa *mySA = (sa *)&myS;
Then you can do this:
printf("I'm really a s.a.bar %d", (*mySA).bar);
Which will print out the appropriate value.
So now you can do:
(*mySA).bar = 22;
printf("%d", myS.b.bar);
You aren't really saving that much typing though.
I would like to know if it is possible to get the type to which I would like to cast dynamically. For eg.
void *ptr;
typedef struct {
..
common_field;
..
} some;
typedef struct {
..
common_field;
..
} some_other;
Now I want to know if I can typecast ptr to type some or some_other dynamically.
precisely what I want to know is if it is possible to have a macro, TYPE_CAST(comdition) which gives me the type like shown below:
(TYPE_CAST(condition)) ptr->common_field
should be equivalent to
((some *) ptr)->common_field or ((some_other *) ptr)->common_field
based on the condition
The following doesn't work, just giving this so that it might be clear to understand c than english:
TYPE_CAST(condition) ((condition) ? (some *) : (some_other *))
Can something along these lines can be done.
Thanks.
That's pretty much not possible. The type of an expression is determined at compile time; it can't depend on any execution time condition.
You can, given a void* that you know points to an object of one type or the other, do something similar (I have not tested this):
condition ? ((some*)ptr)->common_field : ((some_other*)ptr)->common_field
Note that the ->common_field part of the expression has to be repeated; the compiler has to know the type of the left operand of the -> operator.
(Depending on the context, an if/else statement might be clearer.)
A way to design your data structures to avoid your problem could be:
typedef struct {
int common_field;
union {
struct {
int member1;
} some;
struct {
char* member2;
} some_other;
};
} common_struct;
common_struct* ptr;
Then you can easily access the common member with ptr->common_field regardless of which of the two variants you have. I would imagine that the value of this common field will tell you which of the two members of the union you need to use to access the remaining members, which you will then access as ptr->some.member1 or ptr->some_other.member2.
C90 does not support this directly
I assume you want to write a generic list of some sort in c90. Here are some snippets i use in a generic c90 list of mine:
typedef struct {
void *rigth;
void *left;
void *value;
int index;
}GENLIST_node;
#define GENLIST_getValuePtr(NODE, index, valptr) __GENLIST_getValuePtr ((NODE), (index), (void*)(valptr))
using this you can access the content when calling it and always get the rigth type back. Here are some examples:
int *NODEVALA = NULL;
double *NODEVALB = NULL;
char *NODEVALC = NULL;
GENLIST_getValuePtr(&AnyNode, -1, &NODEVALA);
GENLIST_getValuePtr(&AnyNode, -1, &NODEVALB);
GENLIST_getValuePtr(&AnyNode, -1, &NODEVALC);
there are obviousely some parts missing , but what i want to point out is that NODEVALA, NODEVALB and NODEVALC have whatever type you want them to have and the list saves them in form of a void pointer.
in your case this could be done with recursive calls during runtime
switch(condition){
case condition_structA:
structA *X;
getValPtr(&X);
...
break;
structB *X;
getValPtr(&X);
...
case condition_structB:
break;
}
In C90 there is no way the compiler can be used to do things like that automatically. To do this you would need polymorphism and that would be C++ or better.
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).