According to me, it is zero but there seems to be bit confusion here
I have tested it with gcc compiler and it gives me zero as output. I know that in C++, size of an empty class is 1. Let me know if I am missing anything here.
A struct cannot be empty in C because the syntax forbids it. Furthermore, there is a semantic constraint that makes behavior undefined if a struct has no named member:
struct-or-union-specifier:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
struct-or-union:
struct
union
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
/* type-specifier or qualifier required here! */
specifier-qualifier-list:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
struct-declarator:
declarator
declaratoropt : constant-expression
If you write
struct identifier { };
It will give you a diagnostic message, because you violate syntactic rules. If you write
struct identifier { int : 0; };
Then you have a non-empty struct with no named members, thus making behavior undefined, and not requiring a diagnostic:
If the struct-declaration-list contains no named members, the behavior is undefined.
Notice that the following is disallowed because a flexible array member cannot be the first member:
struct identifier { type ident[]; };
The C grammar doesn't allow the contents of a struct to be empty - there has to be at least an unnamed bitfield or a named member (as far as the grammar is concerned - I'm not sure if a struct that contains only an unnamed bitfield is otherwise valid).
Support for empty structs in C are an extension in GCC.
In C++ and empty struct/class member-specification is explicitly permitted, but the size is defined to be 1 - unless as part of the empty base optimization the compiler is allowed to make an empty base class take no space in the derived class.
In C99: "If the struct-declaration-list contains no named members, the behavior is undefined."
The syntax doesn't really allow it anyway, though I don't see anything that says a diagnostic is required, which puts it pretty much back in the "undefined behavior" camp.
on VC 8 It gives error if we try to get the sizeof empty struct, on the other way round on linux with gcc it gives size 1 because it uses gcc extention instead of c language specification which says this is undefined behaviour.
struct node
{
// empty struct.
};
int main()
{
printf("%d", sizeof(struct node));
return 0;
}
on windows vc 2005 It gives compilation error
on linux with gcc it gives size 1 because gcc extension
http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Empty-Structures.html#Empty-Structures
(As Pointed out by Michael Burr)
Related
This question is by mere curiosity. It is not about the empty struct.
I just stumbled over an interesting typo of the kind
struct {
int member1; /*comment*/ ; /* <-- note the ';' */
int member2;
} variable[] = { /* initializers */ };
which the compiler (xc32, derived from gcc) accepted without any
complaints. Of course, I corrected this but the software was running
smoothly before and after the correction and the additional ; seemingly
causes no problems. I then tried various lengthes of ;;; in he struct definition an they seem to make no difference neither to functionality
nor to sizeof. So in a struct any sequence of ;;;; seems to be
equivalent to a single ;.
I couldn't find anything about such "empty members" of a struct/union
in the specification, neither that they are allowed nor that they are
disallowed. To me it seems as if the grammar rejected them. This contrasts
to "empty declarations" ; at the top level of a compilation unit, which the
standard clearly forbids and the "null" statement ; in functions which is a
clearly allowed language feature.
Does anyone know about this behaviour? Is it compiler specific or does the
C specification somehow tolerate such empty struct members?
The syntax is specified in C11 6.7.2.1
struct-declaration:
specifier-qualifier-list struct-declarator-listopt ;
static_assert-declaration
There is 1 semicolon at the end, so that's the only allowed syntax. You cannot skip the semicolon, you can't add extra ones. And that's that.
(You can however have a static assert inside a struct declaration, from C11.)
The standard doesn't talk about that, it's just a gcc tolerance. See 6.7.2.1:
struct-or-union-specifier:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
struct-or-union:
struct
union
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-listopt ;
static_assert-declaration
specifier-qualifier-list:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt
(type-specifier and type-qualifier can't be empty, see the related sections in the standard for details.)
Some compilers, like gcc, tolerate extra semi-colons, but -Wpedantic option reveals that it's only a tolerance:
struct foo {
int a;
;;;
};
int main() {
;;;
}
With -pedantic option gcc complains, not on the main empty statements, but on the extra semicolons of the structure declaration.
<source>:3:5: warning: extra semicolon in struct or union specified [-Wpedantic]
;;;
^
<source>:3:6: warning: extra semicolon in struct or union specified [-Wpedantic]
;;;
^
<source>:3:7: warning: extra semicolon in struct or union specified [-Wpedantic]
;;;
Other compilers may not be that friendly, so the typo must be fixed, since it doesn't bring anything useful.
I have the following struct types:
typedef struct PG_Point PG_Point;
struct PG_Point
{
int x;
int y;
};
typedef struct PG_Size PG_Size;
struct PG_Size
{
int width;
int height;
};
typedef struct PG_Bounds PG_Bounds;
struct PG_Bounds
{
union
{
struct
{
PG_Point topLeft;
PG_Size size;
};
struct
{
struct
{
int x;
int y;
};
struct
{
int width;
int height;
};
};
};
};
with the following initializers:
#define PG_Point_init(ix, iy) {.x=(ix), .y=(iy)}
#define PG_Size_init(iwidth, iheight) {.width=(iwidth), .height=(iheight)}
#define PG_Bounds_init(ix, iy, iwidth, iheight) { \
.topLeft=PG_Point_init((ix),(iy)), \
.size=PG_Size_init((iwidth),(iheight)) }
From what I understand, it's correct in c11 to initialize the fields of an anonymous struct as if they were directly fields of the containing struct? But with gcc 4.9.2, this gives the following warning:
warning: missing initializer for field ‘size’ of ‘struct <anonymous>’ [-Wmissing-field-initializers]
It works if I change the initializer to this version:
#define PG_Bounds_init(ix, iy, iwidth, iheight) {{{ \
.topLeft=PG_Point_init((ix),(iy)), \
.size=PG_Size_init((iwidth),(iheight)) }}}
That is, explicitly having the union and struct as sub aggregates.
Is this even allowed? Do I have to expect other compilers to reject this?
From what I understand, it's correct in c11 to initialize the fields of an anonymous struct as if they were directly fields of the containing struct?
There are two parts to that. First of all, we need to tackle the question of whether such members can be initialized at all, because Paragraph 6.7.2.1/13 identifies anonymous structure and union members as specific kinds of "unnamed members", and paragraph 6.7.9/9 says
Except where explicitly stated otherwise, for the purposes of this subclause unnamed members of objects of structure and union type do not participate in initialization.
The rest of section 6.7.9 (Initialization) nowhere says anything that I would interpret as explicitly applying to anonymous structure and anonymous union members themselves, but I don't think the intent is to prevent initialization of the named members of anonymous members, especially given that they are considered members of the containing structure or union (see below). Thus, I do not interpret the standard to forbid the initialization you are trying to perform.
So yes, I read C11 to allow your initializer and to specify that it has the effect you appear to intend. In particular, paragraph 6.7.2.1/13 of the standard says, in part,
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.
Your initializer therefore satisfies the constraint in paragraph 6.7.9/7, that the designators within specify names of members of the current object (in your case, a struct PG_Bounds). The following paragraphs of section 6.7.9 present the semantics for initializers, and I see no reason to interpret them to specify anything other than initialization of the overall object with the values you have provided.
At this point, I reiterate that gcc is issuing a warning, not rejecting your code, and in this case I think the warning is spurious. I wrote a test program such as I suggested in comments that you do, and tried it on gcc 4.8.5 in C11 mode. Although gcc emitted the same warning you presented (but only with -Wextra enabled), I was able to demonstrate that your initializer initialized all members of a subject struct PG_Bounds to the intended values.
You also observe that gcc does not warn if you change the initializer to a version that uses nested brace-enclosed initializers, and ask
Is this even allowed? Do I have to expect other compilers to reject this?
This could be viewed as more problematic with respect to paragraph 6.7.9/9, so in that sense it is perhaps riskier. I am uncertain whether there is any compiler that actually rejects it or does the wrong thing with it. I think the intent of the standard is to allow this initializer, but I would prefer the other form, myself.
While answer warning: assignment from incompatible pointer type for linklist array, I noticed any undeclared identifier perceded with struct keyword are considered as forward declared identifiers.
For instance the program below compiles well:
/* Compile with "gcc -std=c99 -W -Wall -O2 -pedantic %" */
#include <stdio.h>
struct foo
{
struct bar *next; /* Linked list */
};
int main(void) {
struct bar *a = 0;
struct baz *b = 0;
struct foo c = {0};
printf("bar -> %p\n", (void *)a);
printf("baz -> %p\n", (void *)b);
printf("foo -> %p, %zu\n", (void *)&c, sizeof c); /* Remove %zu if compiling with -ansi flag */
return 0;
}
My question: Which rule guides a C compiler to treat undeclared struct identifiers as forward declared incomplete struct types?
The Standard says (6.2.5.28)
All pointers to structure types shall have the same representation and alignment requirements as each other.
This means the compiler knows how to represent the pointers to any structure, even those that are (yet) undefined.
Your program deals only with pointers to such structures, so it's ok.
It is described in 6.2.5 Types and 6.7.2.3 Tags.
struct identifier is an object type.
6.2.5 Types
The meaning of a value stored in an object or returned by a function is determined by the
type of the expression used to access it. (An identifier declared to be an object is the
simplest such expression; the type is specified in the declaration of the identifier.) Types
are partitioned into object types (types that describe objects) and function types (types
that describe functions). At various points within a translation unit an object type may be
incomplete (lacking sufficient information to determine the size of objects of that type) or
complete (having sufficient information). 37)
37) A type may be incomplete or complete throughout an entire translation unit, or it may change states at
different points within a translation unit.
An array type of unknown size is an incomplete type. It is completed, for an identifier of
that type, by specifying the size in a later declaration (with internal or external linkage).
A structure or union type of unknown content (as described in 6.7.2.3) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or
union tag with its defining content later in the same scope.
6.7.2.3 Tags
All declarations of structure, union, or enumerated types that have the same scope and
use the same tag declare the same type. Irrespective of whether there is a tag or what
other declarations of the type are in the same translation unit, the type is incomplete 129)
until immediately after the closing brace of the list defining the content, and complete
thereafter.
129) An incomplete type may only by used when the size of an object of that type is not needed. It is not
needed, for example, when a typedef name is declared to be a specifier for a structure or union, or
when a pointer to or a function returning a structure or union is being declared. (See incomplete types
in 6.2.5.) The specification has to be complete before such a function is called or defined.
In addition to the answer provided by 2501, and your comment to it that "In my case, there is not even the forward declaration", the following.
Any use of a struct tag counts as a (forward) declaration of the structure type, if it had not been declared before. Although a more formal way would be to say that this simply counts as a type, since the C standard does not mention "forward declarations of structure types", just complete and incomplete structure types (6.2.5p22).
6.7.2 Type specifiers tells us that a struct-or-union-specifier is a type-specifier, and 6.7.2.1 Structure and union specifiers paragraph 1 tells us that that in turn struct identifier is a struct-or-union-specifier.
Suppose you have a linked list declaration, something like
struct node {
struct node *next;
int element;
};
then the "implicit forward declaration" of this incomplete type is essential for this structure to work. After all, the type struct node is only complete at the terminating semicolon. But you need to refer to it in order to declare the next pointer.
Also, a struct node declaration (of incomplete type) can go out of scope, just like any other declaration. This happens for instance if you have some prototype
int function(struct unknown *parameter);
where the struct unknown goes out of scope immediately at the end of the declaration. Any further declared struct unknowns are then not the same as this one. That is implied in the text of 6.2.5p22:
A structure or union type of unknown content (as described in 6.7.2.3)
is an incomplete type. It is completed, for all declarations of that
type, by declaring the same structure or union tag with its defining
content later in the same scope.
That is why gcc warns about this:
foo.c:1:21: warning: 'struct unknown' declared inside parameter list
foo.c:1:21: warning: its scope is only this definition or declaration, which is probably not what you want
You can fix this by putting an extra forward declaration before it, which makes the scope start earlier (and therefore end later):
struct unknown;
int function(struct unknown *parameter);
I think that the most elegant use-case where incomplete struct types are used is something like this :
struct foo
{
struct bar *left;
struct bar *right;
};
struct bar
{
int something;
struct foo *next;
};
I.e. double recursion, where a points to b and b points to a.
Such cases might be a reason why this feature was included in original C language specification.
Original question is whether all struct identifiers are automatically forward declared. I think that it would be better to say that all incomplete struct definitions are automatically considered as forward declaration.
Edit: Following the comment about documentation, let's look at the C language bible : Kerninghan&Ritchie - The C Programming Language, section "6.5 Self-referential Structures" says :
Occasionally, one needs a variation of self-referential structures:
two structures that refer to each other. The way to handle this is:
struct t {
...
struct s *p; /* p points to an s */
};
struct s {
...
struct t *q; /* q points to a t */
};
I agree, that it is possible to implement another way, but I would take this as good motivation from authors of the C language and I agree with them that it is elegant way to implement this.
This is my code:
#include <stdio.h>
typedef struct {
const char *description;
float value;
int age;
} swag;
typedef struct {
swag *swag;
const char *sequence;
} combination;
typedef struct {
combination numbers;
const char *make;
} safe;
int main(void)
{
swag gold = { "GOLD!", 100000.0 };
combination numbers = { &gold, "6503" };
safe s = { numbers, "RAMCON" };
printf("Contents = %s\n", s.numbers.swag->description);
getchar();
return 0;
}
Whenever I compile it with the VS developer console, I get this error: error C2440: 'initializing' : cannot convert from 'combination' to 'swag *'.
However if I use gcc the console just prints: "GOLD!". Don't understand what's going on here.
What you stumbled upon is an implementation-specific variant of a popular non-standard compiler extension used in various C89/90 compilers.
The strict rules of classic C89/90 prohibited the use of non-constant objects in {} initializers. This immediately meant that it was impossible to specify an entire struct object between the {} in the initializer, since that would violate the above requirement. Under that rule you could only use scalar constants between the {}.
However, many C89/90 compilers ignored that standard requirement and allowed users to specify non-constant values when writing {} initializers for local objects. Unfortunately, this immediately created an ambiguity if user specified a complex struct object inside the {} initializer, as in your
safe s = { numbers, "RAMCON" };
The language standard did not allow this, for which reason it was not clear what this numbers initializer should apply to. There are two ways to interpret this:
The existing rules of the language said that the compiler must automatically enter each level of struct nesting and apply sequential initializers from the {} to all sequential scalar fields found in that way (actually, it is a bit more complicated, but that's the general idea).
This is exactly what your compiler did. It took the first initializer numbers, it found the first scalar field s.numbers.swag and attempted to apply the former to the latter. This expectedly produced the error you observed.
Other compiler took a more elaborate approach to that extension. When the compiler saw that the next initializer from the {} list had the same type as the target field on the left-hand side, it did not "open" the target field and did not enter the next level of nesting, but rather used the whole initializer value to initialize the whole target field.
This latter behavior is what you expected in your example (and, if I am not mistaken, this is the behavior required by C99), but your C89/90 compiler behaved in accordance with the first approach.
In other words, when you are writing C89/90 code, it is generally OK to use that non-standard extension when you specify non-constant objects in local {} initializers. But it is a good idea to avoid using struct objects in such initializers and stick to scalar initializers only.
Looks like an issue with the initializers. If you use the proper options with gcc, it will tell you this:
$ gcc -Wall -ansi -pedantic x.c
x.c: In function ‘main’:
x.c:21: warning: initializer element is not computable at load time
x.c:22: warning: initializer element is not computable at load time
which is propably the same issue VS is trying to tell you. You can make these go away if you declare gold and numbers static.
I've seen a lot of questions on this but I'm going to ask the question differently without specific code. Is there a way of EASILY determining what is causing the type to be incomplete? In my case I'm using someone elses code and I'm completely sure I don't have the headers right, but (since computers do this stuff much faster and better than human eyeballs) is there a way to get the compiler to say, "hey you think you have type X at line 34 but that's actually missing." The error itself only shows up when you assign, which isn't very helpful.
I saw a question the other day where someone inadvertently used an incomplete type by specifying something like
struct a {
int q;
};
struct A *x;
x->q = 3;
The compiler knew that struct A was a struct, despite A being totally undefined, by virtue of the struct keyword.
That was in C++, where such usage of struct is atypical (and, it turns out, can lead to foot-shooting). In C if you do
typedef struct a {
...
} a;
then you can use a as the typename and omit the struct later. This will lead the compiler to give you an undefined identifier error later, rather than incomplete type, if you mistype the name or forget a header.
Another possible reason is indirect reference. If a code references to a struct that not included in current c file, the compiler will complain.
a->b->c //error if b not included in current c file
What do you mean, the error only shows up when you assign? For example on GCC, with no assignment in sight:
int main() {
struct blah *b = 0;
*b; // this is line 6
}
incompletetype.c:6: error: dereferencing pointer to incomplete type.
The error is at line 6, that's where I used an incomplete type as if it were a complete type. I was fine up until then.
The mistake is that you should have included whatever header defines the type. But the compiler can't possibly guess what line that should have been included at: any line outside of a function would be fine, pretty much. Neither is it going to go trawling through every text file on your system, looking for a header that defines it, and suggest you should include that.
Alternatively (good point, potatoswatter), the error is at the line where b was defined, when you meant to specify some type which actually exists, but actually specified blah. Finding the definition of the variable b shouldn't be too difficult in most cases. IDEs can usually do it for you, compiler warnings maybe can't be bothered. It's some pretty heinous code, though, if you can't find the definitions of the things you're using.
I don't exactly understand what's the problem. Incomplete type is not the type that's "missing". Incompete type is a type that is declared but not defined (in case of struct types). To find the non-defining declaration is easy. As for the finding the missing definition... the compiler won't help you here, since that is what caused the error in the first place.
A major reason for incomplete type errors in C are typos in type names, which prevent the compiler from matching one name to the other (like in matching the declaration to the definition). But again, the compiler cannot help you here. Compiler don't make guesses about typos.
this error usually shows if the name of your struct is different from the initialization of your struct in the code, so normally, c will find the name of the struct you put and if the original struct is not found, this would usually appear, or if you point a pointer pointed into that pointer, the error will show up.
A - Solution
Speaking for C language, I've just found ampirically that following declaration code will be the solution;
typedef struct ListNode
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
So as a general rule, I give the same name both for both type definition and name of the struct;
typedef struct X
{
// code for additional types here
X* prev; // reference to pointer
X* next; // reference to pointer
} X;
B - Problemetic Samples
Where following declarations are considered both incomplete by the gcc compiler when executing following statement. ;
removed->next->prev = removed->prev;
And I get same error for the dereferencing code reported in the error output;
>gcc Main.c LinkedList.c -o Main.exe -w
LinkedList.c: In function 'removeFromList':
LinkedList.c:166:18: error: dereferencing pointer to incomplete type 'struct ListNode'
removed->next->prev = removed->prev;
For both of the header file declarations listed below;
typedef struct
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Plus this one;
typedef struct ListNodeType
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Outside of possible scenarios involving whole-program optimization, the code code generated for something like:
struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
return blah ? whatever: bar;
}
will be totally unaffected by what members struct foo might contain. Because make utilities will generally recompile any compilation unit in which the complete definition of a structure appears, even when such changes couldn't actually affect the code generated for them, it's common to omit complete structure definitions from compilation units that don't actually need them, and such omission is generally not worthy of a warning.
A compiler needs to have a complete structure or union definition to know how to handle declarations objects of the type with automatic or static duration, declarations of aggregates containing members of the type, or code which accesses members of the structure or union. If the compiler doesn't have the information needed to perform one of the above operations, it will have no choice but to squawk about it.
Incidentally, there's one more situation where the Standard would allow a compiler to require a complete union definition to be visible but would not require a diagnostic: if two structures start with a Common Initial Sequence, and a union type containing both is visible when the compiler is processing code that uses a pointer of one of the structure types to inspects a member of that Common Initial Sequence, the compiler is required to recognize that such code might be accessing the corresponding member of a structure of the other type. I don't know what compilers if any comply with the Standard when the complete union type is visible but not when it isn't [gcc is prone to generate non-conforming code in either case unless the -fno-strict-aliasing flag is used, in which case it will generate conforming code in both cases] but if one wants to write code that uses the CIS rule in such a fashion as to guarantee correct behavior on conforming compilers, one may need to ensure that complete union type definition is visible; failure to do so may result in a compiler silently generating bogus code.