Is there a way to get a pointer to an anonymous struct? With out anonymous structs I could write the following:
struct a{
int z;
};
struct b{
int y;
struct a *x;
}
This works fine, but I only use struct a within struct b and it seems redundant to pollute the global namespace with it. Is there a way I could define a pointer (x) to an anonymous struct. Something that would probably look like the following:
struct b{
int y;
struct {
int z;
} *x;
}
Or is this valid on its own?
Yes you can do this. But there is a complication: there is no way to directly declare another pointer to same type - or an object of that type, because... the struct type is anonymous.
It is still possible to use it however, by allocating memory for it with malloc, as conversions from void * to any pointer to object are possible without an explicit cast:
struct b {
int y;
struct {
int z;
} *x;
} y;
y.x = malloc(sizeof *y.x * 5);
Why would you think that this is better than polluting the namespace is beyond my imagination.
GCC provides the typeof so you can increase insanity by things like
typeof(y.x) foo;
or even declare a structure of that type
struct b y;
typeof(y.x[0]) foo;
foo.z = 42;
y.x = &foo;
Related
Why is the following legal:
typedef struct a aType;
struct a
{
int x;
aType *b;
};
and the following illegal:
void main()
{
typedef struct a aType;
aType someVariable;
struct a
{
int x;
aType *b;
};
}
I'm just curious as in each case it is forward referencing and as far as I know, at least for functions and variables, forward referencing is not legal.
Also, would the answer for this be the same for C++ as well?
You are allowed to create pointers to incomplete types, because the size of the pointer object does not depend on the size of the pointed-to type. Pointers to different struct types have the same size and representation, regardless of the size of the struct type itself.
You are not allowed to create instances of incomplete types, since the size of the type isn't known.
This of it this way:
typedef struct a aType;
struct a { int x; aType *b; };
is the same as:
struct a;
typedef struct a aType;
struct a { int x; aType *b; };
So you're forward-declaring a struct, typedefing it and later defining it. Perfectly fine.
Now the second example:
typedef struct a aType;
aType someVariable;
struct a { int x; aType *b; };
This has nothing to do with the fact that it's in local scope.
What's happening is this:
struct a;
typedef struct a aType;
aType someVariable; // error: when it gets here, aType is still incomplete
struct a { int x; aType *b; };
aType someVariable; // perfectly fine, aType not incomplete
Remember that compilation happens in order. When you try to declare someVariable the compiler doesn't know what struct a is yet, so it doesn't know its size, hence it doesn't know how much memory to allocate for it, hence a compile error. Declaring it after aType is defined works as expected.
If I have these two structs:
struct
{
int x;
} A;
struct
{
int x;
} B;
then making A = B; results in a compilation error because the two anonymous structs are not compatible.
However if I do:
typedef struct
{
int x;
} S;
S A;
S B;
A = B; is a legal assignment because they are compatible.
But why? With typedef I understand that the compiler makes this when meet S A and S B:
struct { int x; } A;
struct { int x; } B;
so A and B should not be compatible...
Each anonymous struct declaration is a distinct type; this is why you get a type mismatch when trying to assign one to the other.
A typedef, however, declares an alias (i.e. a new name for something that already exists) for a type (it does not create a new type).
A typedef is also not a simple text replacement, like a preprocessor macro. Your statement
I understand that the compiler make this when meet S A and S B:
struct { int x; } A;
struct { int x; } B;
is where your understanding is wrong.
When you use the type alias S, as in
S A;
S B;
the types of both objects A and B are the same by definition and assigning one to the other is possible.
This is because C treats every untagged struct as a new kind of struct, regardless of the memory layout. However, typedef struct { } name; cannot be used if you want to use the struct in a linked list. You'll need to stick with defining a structure tag in this case, and typedef the tagged struct instead.
struct DistanceInMeter /* Anonymous 1 */
{
int x; /* distance */
};
struct VolumeInCC /* Anonymous 2 */
{
int x; /* volume */
};
struct DistanceInMeter A;
struct VolumeInCC B;
...
A = B; /* Something is wrong here */
Equating different type doesn't always make sense and thus is not allowed.
typedef struct DistanceInMeter /* Anonymous 1 */
{
int x; /* distance */
} Dist_t;
Dist_t C, D;
...
C = D; /* Alright, makes sense */
Having a struct -
typedef struct Point{
....
}
I want to write its prototype before the main() , something like -
typedef struct Point ;
int main() {
Point p1 ,p2 ;
...
}
typedef struct Point {
int x;
int y;
} Point;
The above gives me error - unknown type name 'Point' .
How could I achieve that right ?
Edit:
I know that it would be work if I define to struct before the main() . I just want to know whether it have any prototye similarly to function prototye.
You cannot do this, because the C language is organized around one pass compilation. At the point where a type name is used to declare or define something, that type have been previously declared.
There is a relaxation of this rule, namely: you can define incomplete types in C. However, incomplete types cannot be used to define objects: at least, not certain kinds of objects. So this is invalid:
struct foo; /* introduces incomplete type foo */
struct foo x; /* incomplete type for external definition is okay, as long
as the type is completed before the end of the translation unit. */
extern struct foo e; /* incomplete type for external declaration is allowed even if
the type is not completely known in this translation unit
at all. A definition of the object e must exist somewhere
in the linked program---unless e is not used; then a definition
need not exist at all. */
void func(void)
{
struct foo y; /* incomplete type not okay here */
}
struct bar {
struct foo z; /* not okay here */
};
struct foo {
char *s;
}; /* struct foo is now a complete type, but it's too late in the file */
The last declaration above, which completes the type struct foo allows for the struct foo x; definition to be valid. So there is some "lexically retroactive" action in the C type system; it's just not general.
The situations marked as "not okay" require the struct type to be complete at that point in the source code.
If you want to define local variables of type Point in your main function, that type must be declared and complete prior to that function. If that type is not complete, you can still define variables of type Point *: pointer to Point. But these pointers cannot be dereferenced.
This declaration:
typedef struct Point;
is not valid in C.
How could I achieve that right ?
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
}
You cannot achieve the same with struct Point declaration after main because the implementation has to know the storage of Point objects p1 and p2 when you declare them in main.
You won't be able to do that because the compiler would need to know how much space to allocate for Point when you allocate it. Prototyping wouldn't give you this information.
You could do this, as the size of the pointer will be known:
typedef struct Point Point;
int main() {
Point * p1;
}
struct Point {
int x;
int y;
};
I don't know if that will meet your needs, though
The problem is that you are declaring your struct after main.
typedef struct Point ; // you dont really need this.
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
...
}
even better is this:
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
...
}
Put the declaration in another file (e.g., Point.h) that gets included at the top of your main() file, and put the definition in a separately-compiled implementation file (e.g., Point.cpp).
I have a question in initializing my structure array inside a structure array. for example if I have a code as below:
#include <stdio.h>
int main() {
typedef struct {
int a;
int b;
int c;
} FIRST_T;
typedef struct {
int x;
int y;
int z;
FIRST_T *p;
} SECOND_T;
FIRST_T p1[]={{1,2,3},{3,4,5},{6,7,8}};
FIRST_T p2[]={{4,5,6},{7,8,9}};
SECOND_T my_second[]=
{
{1,2,3,p1},
{4,5,6,p2}
};
}
if I have to initialize my first array in second array intialization part itself, then how would I write my typedef of SECOND_T?
like
SECOND_T my_second[]=
{
{1,2,3,{{1,2,3},{4,5,6},{7,8,9}}},
{4,5,6,{{1,1,1},{2,2,2}}}
};
then how should be my SECOND_T?
I am sure I can't define it as:
typedef struct {
int x;
int y;
int z;
FIRST_T p[]; //(I know its a blunder)
} SECOND_T;
Please help.
You can't define a type with unbounded array in C, you have to specify the dimension. So you either do:
typedef strut {
int x;
int y;
int z;
FIRST_T f[SOME_VALUE];
} SECOND_T;
and then initialize SOME_VALUE count of members always, or do it the way you did.
I don't think you can do this, i.e, initialize the FIRST_T inside the initialization of SECOND_T, other than the first way you do it. Think about it, how can the compiler tell how many FIRST_T are there in SECOND_T? The problem here is, you can NOT define an array of flexible size struct statically.
you can't to do like that:
SECOND_T my_second[]=
{
{1,2,3,{{1,2,3},{4,5,6},{7,8,9}}},
{4,5,6,{{1,1,1},{2,2,2}}}
};
with
typedef struct {
int x;
int y;
int z;
FIRST_T p[]; //(I know its a blunder)
} SECOND_T;
becase the compiler don't know how to malloc memory for this struct. if you must do like this, you should define
typedef struct { int x,y,z; FIRST_T p[CONST_VALUE];}SECOND_T;
but I advise you use the first style that you write.
I don't know if I completely capture the question that you have. If it is that you want to avoid to have to declare an auxiliary variable for the pointers in the structure you can use a compound literal as follows:
SECOND_T my_second[] = {
{1,2,3, &(FIRST_T){{1,2,3},{3,4,5},{6,7,8}}},
{4,5,6, &(FIRST_T){{4,5,6},{7,8,9}}}
};
You'd have a compiler that complies to C99 for that.
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;