Why must a struct member always have an Identifier? The answer of course is because that is how the language is defined, but I'd like to understand the reason behind it.
typedef union {
int a;
struct {
int a; //Why is an identifier necessary here?
int b;
} s;
} u;
There are grammar complications here. Consider int a, b, c;. That declares three objects. int a, b; declares two, and int a; declares one. So how many should int; declare? When a declaration with no declarator appears in other contexts, it does not declare any object. For example, struct foo { int x; }; defines the type struct foo, but it does not declare an object of that type.
We could make an exception for declarations in structures, and say that, if they have no declarators, then they declare one unnamed member. But then we are introducing another special case in to the grammar. Then struct foo { int x; };, which has no declarator, would declare a member object of type struct foo when it appears inside a structure definition, but it would not declare any object when it appears outside of a structure definition.
So this adds complications to the language. And it is not necessary; somebody who wants a member in a structure can always give it a name and can choose a name that will not interfere with other code.
Actually, bit field members do not need a name, at least according to gcc -std=c99 -Wall -Wextra -pedantic, which gives no warning when compiling this code:
struct Foo
{
char x;
unsigned :8;
};
If you really don't want to have an identifier for a member that isn't a bit-field, you can name it something like _reserved0 to explicitly show that this is just reserved space that you don't want to access from your code.
I don't know the opinions of the people who wrote the C standard. Maybe they were thinking a struct member without a name was almost always a bug (i.e. the programmer forgot the name), and they wanted to help people catch those bugs, but they made a few exceptions to the rule.
//Why is an identifier necessary here?
This a is distinct from the a outside the structure. The compiler needs to know which one you want to access
If you use distinct names you can use anonymous structure in your union
typedef union {
int a;
struct {
int b;
int c;
};
} u;
u foo(int x, int y, int z)
{
u un;
u.a = x;
u.b = y;
u.c = z;
}
Related
#define MyStruct(T) struct {T data;}
void foo(MyStruct(int) s);
void foo(MyStruct(int) s) {
return;
}
int main(void) {
//...
return 0;
}
This results in an error:
main.c:7:6: error: conflicting types for 'foo'
void foo(MyStruct(int) s) {
^
main.c:5:6: note: previous declaration is here
void foo(MyStruct(int) s);
^
There's no error if I create a typedef, such as typedef MyStruct(int) MyIntStruct; and use that.
So my question is, why do I get the conflicting type error? Are all anonymous structs unique, like the compiler won't determine whether they're the exact same type?
First, these are structure declarations without tags, not anonymous structures. An anonymous structure is a structure without a name, not a structure declaration without a tag. For example:
struct outer
{
struct inner { int x; int y; };
int z;
} s;
In this code, the struct member inside s does not have a member name, so it is anonymous. We have no name that can refer to that structure, and we refer to its members as s.x and s.y, rather than s.something.x and s.something.y.
The reason each declaration of a structure without a tag declares a distinct type is C 2018 6.7.2.3 5 says:
… Each declaration of a structure, union, or enumerated type which does not include a tag declares a distinct type.
A reason for this is sometimes we use structures that have identical contents for different purposes. For example, we might have a structure with two double values that we use for complex numbers (real and imaginary parts) and a structure with two double values that we use for points in a plane (x and y coordinates):
typedef struct { double d[2]; } ComplexNumber;
typedef struct { double d[2]; } Point;
Having the compiler treat these as different types means it can give us warnings about mistakes like passing a Point as an argument where a Complex is expected.
As you have noted, a typedef creates a new name for a type. Then using the typedef name refers to that existing type. It does not “repeat” the declaration of the struct and create a new type.
If I have these structures:
typedef struct { int x; } foo;
typedef struct { foo f; } bar;
Normally you would access x through b.f.x, but is there a way to set this up so that you can access element x without referring to f?
bar b;
b.x = ...
My first intuition is that you can't since there would be a possibility for name conflicts if two sub structures both had a member x and I can't figure out what the compile error would be. However, I recall working in some frameworks where this was possible.
In C++ I worked in a framework once where bar existed, and you could access its members as member variables this->x from a different class. I'm trying to figure out how that could be done.
You can with C11:
§ 6.7.2.1 -- 11
An unnamed member whose type specifier is a structure specifier with no tag is called an
anonymous structure; an unnamed member whose type specifier is a union specifier with
no tag is called an anonymous union. The members of an anonymous structure or union
are considered to be members of the containing structure or union. This applies
recursively if the containing structure or union is also anonymous.
So this code might work:
#include <stdio.h>
typedef struct { int x; } foo;
typedef struct { foo; } bar;
int main(void)
{
bar b;
b.x = 1;
printf("%d\n", b.x);
}
The problem here is that different compilers disagree in my tests on whether a typedef is acceptable as a struct specifier with no tag The standard specifies:
§ 6.7.8 -- 3
In a declaration whose storage-class specifier is typedef, each declarator defines an
identifier to be a typedef name that denotes the type specified for the identifier in the way
described in 6.7.6. [...] A typedef declaration does not introduce a new type, only a
synonym for the type so specified.
(emphasis mine) -- But does synonym also mean a typdef-name specifier is exchangeable for a struct specifier? gcc accepts this, clang doesn't.
Of course, there's no way to express the whole member of type foo with these declarations, you sacrifice your named member f.
Concerning your doubt about name collisions, this is what gcc has to say when you put another int x inside bar:
structinherit.c:4:27: error: duplicate member 'x'
typedef struct { foo; int x; } bar;
^
To avoid ambiguity, you can just repeat the struct, possibly #defined as a macro, but of course, this looks a bit ugly:
#include <stdio.h>
typedef struct { int x; } foo;
typedef struct { struct { int x; }; } bar;
int main(void)
{
bar b;
b.x = 1;
printf("%d\n", b.x);
}
But any conforming compiler should accept this code, so stick to this version.
<opinion>This is a pity, I like the syntax accepted by gcc much better, but as the wording of the standard doesn't make it explicit to allow this, the only safe bet is to assume it's forbidden, so clang is not to blame here...</opinion>
If you want to refer to x by either b.x or b.f.x, you can use an additional anonymous union like this:
#include <stdio.h>
typedef struct { int x; } foo;
typedef struct {
union { struct { int x; }; foo f; };
} bar;
int main(void)
{
bar b;
b.f.x = 2;
b.x = 1;
printf("%d\n", b.f.x); // <-- guaranteed to print 1
}
This will not cause aliasing issues because of
§ 6.5.2.3 -- 6
One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members
C: Highly unrecommended, but doable:
#include <stdio.h>
#define BAR_STRUCT struct { int x; }
typedef BAR_STRUCT bar;
typedef struct {
union {
bar b;
BAR_STRUCT;
};
} foo;
int main() {
foo f;
f.x = 989898;
printf("%d %d", f.b.x, f.x);
return 0;
}
Anonymous structs are a widly-spread extension in standards before C11.
C++:
The same as in C, you can do here but anonymous structs are not part of any C++ standard, but an extension.
Better use inheritance, or do not use this shortcut at all.
Of course, do not use something like #define x b.x)).
In C you can't access members of members like this.
You can however access members of an anonymous inner struct:
struct bar {
struct {
int x;
}
};
...
struct bar b;
b.x = 1;
In C++ you use inheritance:
struct foo {
int x;
};
struct bar: public foo {
};
...
struct bar b;
b.x = 1;
In C (99 and onward) you can access the common initial sub-sequence of union members, even if they weren't the last member written to1.
In C11, you can have anonymous union members. So:
typedef struct { int x; } foo;
typedef struct {
union {
foo f;
int x;
};
} bar;
Yes, that applies to structures. But according to the standard:
A structure pointer, suitably converted, points to the first member.
A union pointer, suitably converted, points to any union member.
So their location in memory is the same.
This is not possible in C. In C++ however you can use inheritance which is probably what you were thinking about.
In C++, you can use inheritance and member name conflicts are sort of resolvable with :: and treating the base classes as members.
struct foo { int x; };
struct bar : foo { };
struct foo1 { int x; };
struct bar1 : foo1 { char const* x; };
bar b;
bar1 b1;
int main()
{
return b.x + b1.foo1::x;
}
In standard C, it's impossible, however several compilers (gcc, clang, tinycc) support a similar thing as an extension (usually accessible with -fms-extensions (on gcc also with -fplan9-extensions which is a superset of -fms-extensions)), which allows you to do:
struct foo { int x; };
struct bar { struct foo; };
struct bar b = { 42 };
int main()
{
return b.x;
}
However, there's no resolution for conflicting member names with it, AFAIK.
In C++, it is possible in two ways. The first is to use inheritence. The second is for bar to contain a reference member named x (int &x), and constructors that initialise x to refer to f.x.
In C, it is not possible.
Since the C standard guarantees that there isn't padding before the first member of a struct, there isn't padding before the foo in bar, and there isn't padding before the x in foo. So, a raw memory access to the start of bar will access bar::foo::x.
You could do something like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct _foo
{
int x;
} foo;
typedef struct _bar
{
foo f;
} bar;
int main()
{
bar b;
int val = 10;
// Setting the value:
memcpy(&b, &val, sizeof(int));
printf("%d\n", b.f.x);
b.f.x = 100;
// Reading the value:
memcpy(&val, &b, sizeof(int));
printf("%d\n", val);
return 0;
}
As others have noted, C++ offers a more elegant way of doing this through inheritance.
I declared this structure in global scope,
struct a{
int a;
int x;
union b{
int a;
int b;
int y;
};
};
And then declared an union inside main,
union b a;
And this is not giving any errors. But if declare union 'a' in the definition of structure, like:
struct a{
int a;
int x;
union b{
int a;
int b;
int y;
}a;
};
It gives error "duplicate member a". (WE USED THE SAME NAME 'a' IN THE PREVIOUS CASE)
Why does one work and another does not?
Secondly, how can we use the union declared inside struct, independently, but can't use any other integer variable, say 'x'?
Like, i can perform the following successfully:
union b z; //works in this case, BUT not if we declare 'z' with the definition.
z.y=6; //works
x=6; //gives error
(i understand we are declaring union inside main, but its definition in inside the struct. Like, struct.union.union_variable makes sense, but having union.union_variable directly make it kind of independent. Shouldn't it be treated like 'x'?)
It gives error "duplicate member a". (WE USED THE SAME NAME 'a' IN THE PREVIOUS CASE) Why does one work and another does not?
Because your struct has now two members named a: first one is an int and second one is of type b (your union). You wouldn't be surprised to see this doesn't compile:
struct a {
int a;
float a;
};
In your case you have exactly same situation, imaging you defined b outside struct and you try to use it like this:
struct a {
int a;
union b a;
};
Secondly, how can we use the union declared inside struct, independently, but can't use any other integer variable, say 'x'? Like, i can perform the following successfully:
Where is x declared? You don't have any local variable named x (what you may have is a struct member named x but then you need such structure). One of following (according to what you're trying to do):
int x = 6;
struct a w;
a.x = 6;
In gcc it is possible to create an anonymous struct, like this:
struct test2 {
struct {
int x;
int y;
};
int z;
};
But when I try to do the same thing with a pre-defined version of the anonymous struct, it fails:
struct test1 {
int x;
int y;
};
struct test2 {
struct test1;
int z;
};
The reason I want to do this is that I want to define a struct which contains a set of function pointers corresponding to "member functions" of a C class. If I don't include the struct anonymously, then I wind up having to do something obnoxious like this:
object->API->function(object,...);
which just plain doesn't work for some things I need to do (for instance, since "object.API" doesn't match "object", it makes it difficult or impossible to do automatic bindings from other languages which support hiding of the object pointer.)
At the moment, I just copy/paste the functions, but this is tedious and error prone. I could use the C pre-processor, but it seems just ugly to create a macro which has a bunch of function prototypes in it.
struct test1 is the name of the type of the struct. You are lacking a name for the field (and you cannot have "anonymous" fields other than inline-defined structs or unions).
struct test2 {
struct test1 myStructTest1;
int z;
};
EDIT: Apparently there's a GCC extension that allows you do that: -fms-extensions
Unless -fms-extensions is used, the unnamed field must be a structure or union definition without a tag (for example, struct { int a; };'). If -fms-extensions is used, the field may also be a definition with a tag such asstruct foo { int a; };', a reference to a previously defined structure or union such as `struct foo;', or a reference to a typedef name for a previously defined structure or union type.
struct s1 { int a; };
struct s2 { struct s1; };
Anonymous structs have been added in the C11 standard, so
typedef struct {
struct {int a, b};
int c;
} abc_struct;
is valid and standard. Is it also within the standard to use a typedef in place of the full struct declaration? E.g.:
typedef struct {
int a, b;
} ab_struct;
typedef struct {
ab_struct;
int c;
} abc_struct;
The GCC documentation says that this is a Plan 9 extension, but then it works in the
few compilers I've tried (including GCC...). By my reading of the standard itself,
I think it's OK, but this is the sort of close reading that's easy to screw up.
This was apparently asked in a question to the C committee by Joseph S. Myers of the gcc team. And the answer is no, it is not valid in C11.
See the answer here:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1549.pdf
And Myers's comment:
This week's London WG14 meeting agreed to disallow the use of typedefs in declaring anonymous structure and union fields, as per N1549.
source http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01151.html
The question was asked in SC22WG15.12205 see 5.28 SC22WG14.12205, Anonymous Structures (N1425) in http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1490.pdf
Actually your second snippet is fraught with peril and is not equivalent to the first one without explicitly specifying -fplan9-extensions in gcc.
In particular ab_struct; declaration on line 6 does NOTHING (as per gcc warning). Just pasting your second snippet in foo.c generates:
foo.c:6: warning: declaration does not declare anything
And in particular if you were to try:
typedef struct {
int a, b;
} ab_struct;
typedef struct {
ab_struct;
int c;
} abc_struct;
int main() {
abc_struct abc;
abc.a = 5;
return 0;
}
you would get a syntax error on line 13 abc.a = 5; without the -fplan9-extensio.
whereas using the top snippet your anonymous structure will work as you are thinking it should. Namely:
typedef struct {
struct {
int a, b;
};
int c;
} abc_struct;
int main() {
abc_struct abc;
abc.a = 5;
return 0;
}
Well, I'm afraid I haven't bothered to get the finished standard yet, but here's what the final draft says:
An unnamed member whose type specifier is a structure specifier with no tag is called an anonymous structure; an unnamed member whose type specifier is a union specifier with no tag is called an anonymous union.
I can only interpret the as that only struct {}; and union {}; can be an anonymous struct/union.