Empty structure in C - c

I have a structure with no members (for the moment) and I would like to know if it is possible to suppress the warning I get:
warning: struct has no members
Is it possible to add a member and keep the sizeof the struct zero? Any other solution?

In c the behaviour of an empty structure is compiler dependent versus c++ where it is part of the spec (explanations here)
C++
A class with an empty sequence of members and base class objects is an empty class. Complete objects and member subobjects of an empty class type shall have nonzero size.
in C it is rather more murky since the c99 standard has some language which implies that truly empty structures aren't allowed (see TrayMan's answer) but many compilers do allow it (e.g gcc).
Since this is compiler dependent it is unlikely that you will get truly portable code in this case. As such non portable ways to suppress the warning may be your best bet.
In VS you would use #pragma warning
in GCC from 4.2.1 you have Diagnostic Pragmas

if you just need the struct symbol for casting and function arguments then just:
typedef struct _Interface Interface;
this will create the symbol for an opaque type.

Technically this isn't even valid C.
TrayMan was a little off in his analysis, yes 6.2.6.1 says:
Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.
but tie that with 6.2.5-20, which says:
— A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.
and now you can conclude that structures are going to be one or more bytes because they can't be empty. Your code is giving you a warning, while the same code will actually fail to compile on Microsoft's Visual Studio with an error:
error C2016: C requires that a struct or union has at least one member
So the short answer is no, there isn't a portable way to avoid this warning, because it's telling you you're violating the C standards. You'll have to use a compiler specific extension to suppress it.

C99 standard is somewhat ambiguous on this, but seems to say that an empty struct should have non-zero size.
6.2.6.1
Except for bit-fields, objects are composed of contiguous sequences of one or more bytes,
the number, order, and encoding of which are either explicitly specified or
implementation-defined.

struct zero_information { int:0; };
The above code snippet will yield a non-zero value from sizeof(struct zero_information), but it might help you get what you looking for as 100% of all the storage that is allocated for it, is padding (only accessible through hacks, although I don't remember from the top of my head if acceding the padding is undefined behavior).

Is it possible to add a member and keep the sizeof the struct zero?
Nope. FWIW, C++ allows empty structs but the sizeof() is always non-zero for an empty struct.
Any other solution?
Not any easy ones. It's worth noting that empty structs are only somewhat supported in C and disallowed in C99.
Empty structs are supported in C++ but different compilers implement them with varying results (for sizeof and struct offsets), especially once you start throwing inheritance into the mix.

If you're not requiring "too strict" adherence, you might get away with this:
struct empty {
char nothing[0];
};
This is a GCC extension, though.
I was kind of hoping I'd be able to use the C99 feature called "flexible arrays", declared like this:
struct empty99
{
char nothing[]; // This is a C99 "flexible array".
};
but that doesn't work; they require that there is at least one normal struct member first, they can't be the only member.

Related

How are constant struct members handled in C?

Is it OK do do something like this?
struct MyStruct {
int x;
const char y; // notice the const
unsigned short z;
};
struct MyStruct AStruct;
fread(&MyStruct, sizeof (MyStruct), 1,
SomeFileThatWasDefinedEarlierButIsntIncludedInThisCodeSnippet);
I am changing the constant struct member by writing to the entire struct from a file. How is that supposed to be handled? Is this undefined behavior, to write to a non-constant struct, if one or more of the struct members is constant? If so, what is the accepted practice to handle constant struct members?
It's undefined behavior.
The C11 draft n1570 says:
6.7.3 Type qualifiers
...
...
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.
My interpretation of this is: To be compliant with the standard, you are only allowed to set the value of the const member during object creation (aka initialization) like:
struct MyStruct AStruct = {1, 'a', 2}; // Fine
Doing
AStruct.y = 'b'; // Error
should give a compiler error.
You can trick the compiler with code like:
memcpy(&AStruct, &AnotherStruct, sizeof AStruct);
It will probably work fine on most systems but it's still undefined behavior according to the C11 standard.
Also see memcpy with destination pointer to const data
How are constant struct members handled in C?
Read the C11 standard n1570 and its §6.7.3 related to the const qualifier.
If so, what is the accepted practice to handle constant struct members?
It depends if you care more about strict conformance to the C standard, or about practical implementations. See this draft report (work in progress in June 2020) discussing these concerns. Such considerations depend on the development efforts allocated on your project, and on portability of your software (to other platforms).
It is likely that you won't spend the same efforts on the embedded software of a Covid respirator (or inside some ICBM) and on the web server (like lighttpd or a library such as libonion or some FastCGI application) inside a cheap consumer appliance or running on some cheap rented Linux VPS.
Consider also using static analysis tools such as Frama-C or the Clang static analyzer on your code.
Regarding undefined behavior, be sure to read this blog.
See also this answer to a related question.
I am changing the constant struct member by writing to the entire struct from a file.
Then endianness issues and file system issues are important. Consider perhaps using libraries related to JSON, to YAML, perhaps mixed to sqlite or PostGreSQL or TokyoCabinet (and the source code of all these open source libraries, or from the Linux kernel, could be inspirational).
The Standard is a bit sloppy in its definition and use of the term "object". For a statement like "All X must be Y" or "No X may be Z" to be meaningful, the definition of X must have criteria that are not only satisfied by all X, but that would unambiguously exclude all objects that aren't required to be Y or are allowed to be Z.
The definition of "object", however, is simply "region of data storage in the execution environment, the contents of which can represent values". Such a definition, however, fails to make clear whether every possible range of consecutive addresses is always an "object", or when various possible ranges of addresses are subject to the constraints that apply to "objects" and when they are not.
In order for the Standard to unambiguously classify a corner case as defined or undefined, the Committee would have to reach a consensus as to whether it should be defined or undefined. If the Committee members fundamentally disagree about whether some cases should be defined or undefined, the only way to pass a rule by consensus will be if the rule is written ambiguously in a way that allows people with contradictory views about what should be defined to each think the rule supports their viewpoint. While I don't think the Committee members explicitly wanted to make their rules ambiguous, I don't think the Committee could have been consensus for rules that weren't.
Given that situation, many actions, including updating structures that have constant members, most likely falls in the realm of actions which the Standard doesn't require implementations to process meaningfully, but which the authors of the Standard would have expected that implementations would process meaningfully anyhow.

Is there a size limit to how many members or the type types of variables a structure may contain?

I ran into some weird issues (at compile time) with my embedded C code when I increased the size of the array from size [2] to [27] which contained structured metadata. So it is obvious that this is a nested structured style program and NOT my original work!
I remember in assembly code instructions, there used to be a JMP FAR, JMP NEAR/SHORT.. Is there any such limitations in structures (obviously there is no jump in structures). Could there be a condition that the compiler cannot assign a contiguous memory block for a structure because there is a limit to it and fails during compilation.
SOME CLUE: The fix as i recall was to move the member (array member)from original structure to another nested structure. That's the reason why i deduced that there maybe a limitation.
//STRUCTURES
typedef UINT8 P_Name_t[5];
typedef UINT8 ChipSN_t[3];
typedef struct
{
ChipSN_t ChipSN;
<other members>
} ChipIdent_t;
typedef struct Data_t
{
ChipIdent_t ReadOnlyMemID;
<other members>
} Data_t;
typedef struct
{
P_Name_t NameOfPart;
<other members>
} Log_t;
Data_t Data_Src;
typedef struct
{
P_Name_t NameOfPart;
ChipSN_t ChipSN;
}PartNum_ID_t;
typedef struct
{
PartNum_ID_t PN_ChipID[27];
<other members>;
}
According to standard, there is a limitation; but the limitation is much more than the size you mentioned here. C89 and C99 standard has the limit of 1023 structure members. See below text from the standard.
5.2.4.1 Translation limits
— 1023 members in a single structure or union
So looks like if your code is correct and limited to 1023 structure members the compiler you are using may have the limitation.
There may indeed be a limit to the number of structure elements your compiler can handle for a single structure, but as MCG quoted from the C Standard, this limit must be at least 1023 for compliant compilers and most compilers have higher limits or no practical limits at all.
I suspect the problem is elsewhere:
The Makefile for your project may have incomplete dependencies on the header file with the structure definitions: modules compiled with different definitions will be incompatible and produce undefined behavior. Remove all object files and recompile the project.
Some assembly modules may rely on the original structure layout: changing the definition will only affect the recompiled C modules.
Some library modules or OS system calls may rely on the original layout. Recompiling all libraries or even patching the OS may be required.
Some functions may rely on the original layout and use casts to access some of the structures via another type. Changing the layout may break such code, which is brittle anyway as even changing compilers may produce similar problems.
It is also possible that some of the type be multiply defined in different modules. This is poor and very error prone coding style as changing only one of the definitions will lead to undefined behavior when the object modules are linked together.

Custom user-data reservation in ansi-c

I have a library with the following structure:
struct frame_meta_data
{
uint8_t id;
uint8_t general_field_1;
uint8_t general_field_2;
...
uint8_t user_data[16];
};
And I would like users of the library to be able to save custom data into frame objects (that's what the user_data field is for).
However when trying to cast user_data into a custom structure:
frame_meta_data cur_frame;
...
#define USER_HDR ((struct my_user_header*)cur_frame.user_data)
I get the following error:
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
#define USER_HDR ((struct my_user_header*)cur_frame.user_data)
How can I work around this?
Thanks in advance.
Reinterpreting addresses like that isn't allowed by the C standard. Strict aliasing means that compilers are free to assume two pointers of different types will never point at the same object, and then make all sorts of optimizations based of that.
Your code violates the C standard and has undefined behavior on account of that. But you can fix it still. Like melpomene suggested in the comments, don't cast, but use memcpy:
struct my_user_header obj;
memcpy(&obj, cur_frame.user_data, sizeof obj);
Alternatively, some compilers allow you to write non-standard code with compiler option, such as GCC's -fno-strict-aliasing.
If you know what you are doing, you can disable that warning. There is however a potential problem.
Assume that the structure you want to use contains something that is larger than 1 byte. For example a 4-byte integer. Now if you simply cast that user_data field to your structure it is possible that the int is not aligned to 4-byte boundary as it should be. This might result in a runtime exception in some architectures.
Using memcpy should solve that problem though. And remove the warning.
I suspect it's because you're involving copies of this USR_DATA macro expression in multiple accesses to the data area, and it's confusing the compiler. Or perhaps you're even mixing USR_DATA accesses with manipulations of the underlying char array.
If the data area is only being initialized and accessed as that given user data type, there isn't any aliasing going on. Ensure you use it that way.
I would provide an external (as in, non-inlined, external linkage) API function which, given a frame object, returns a void * to the associated user data:
struct foobar *fbs = (struct foobar *) frame_get_userdata(fr);
// now work just with fbs
The cast isn't necessary; that's my style.
Depending on what precedes the user data, it might not be suitably aligned for arbitrary use. One easy way to fix that would be to make it the first struct member, if that option is available. Otherwise there are various fairly portable tricks involving making a union between a char array and various types like long double and whatnot, or else using compiler-specific constructs, like __attribute__((aligned)) with GCC.

How to ensure structures are completly initialized (by name) in GCC?

How do I ensure each and every field of my structures are initialized in GCC when using designated initializers? (I'm especially interested in function pointers.) (I'm using C not C++.)
Here is an example:
typedef struct {
int a;
int b;
} foo_t;
typedef struct {
void (*Start)(void);
void (*Stop)(void);
} bar_t;
foo_t fooo = {
5
};
foo_t food = {
.b=4
};
bar_t baro = {
NULL
};
bar_t bard = {
.Start = NULL
};
-Wmissing-field-initializers does not help at all. It works for fooo only in GCC (mingw 4.7.3, 4.8.1), and clang does only marginally better (no warnings for food and bard).
I'm sure there is a reason for not producing warnings for designated initializer (even when I explicitly ask for them) but I want/need them. I do not want to initialize structures based on order/position because that is more error prone (for example swapping Start and Stop won't even give any warning). And neither gcc nor clang will give any warning that I failed to explicitly initialize a field (when initializing by name). I also don't want to litter my code with if(x.y==NULL) lines for multiple reasons, one of which is I want compile time warnings and not runtime errors.
At least splint will give me warnings on all 4 cases, but unfortunately I cannot use splint all the time (it chokes on some of the code (fails to parse some C99, GCC extensions)).
Note: If I'm using a real function instead of NULL GCC will also show a warning for baro (but not bard).
I searched google and stack overflow but only found related questions and have not found answer for this specific problem.
The best match I have found is 'Ensure that all elements in a structure are initialized'
Ensure that all elements in a structure are initialized
Which asks pretty much the same question, but has no satisfying answer.
Is there a better way dealing with this that I have not mentioned?
(Maybe other code analysis tool? Preferably something (free) that can be integrated into Eclipse or Visual Studio...)
If I'm not mistaken, the C standards specify that the other fields are automatically initialized with 0.
So what you are asking for - a compilation error when fields are not initialized - would be out of line with the C (modern?) specifications.
C99 standard, page 127 in: http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration.
gccs -Wmissing-field-initializers is documented to not warn with designated initializers. There is a request for an enhancement -Wmissing-field-initializers=2 that would then warn also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39589
So I suggest you add your wish to that bug report, or maybe even provide a patch. From my experience with open-source software, adding a patch is best.
The four ways you have showed all initialize the rest of the structure. It's initialized to 0 (or the type equivalent).

Pointer to array of opaque structures

I have an odd problem with gcc 4.3 and I wanted to know if it is a specific problem with the compiler or if it is a general C problem.
Granted, I use a really odd construct, but I like it, because it allows me to enforce some rules that otherwise would not be possible.
The project is split in several modules and each module has a structure that is opaque.
There's a typedef struct <tag> <type> declaration in the header and in 1 c file, there is a struct tag { ... }; and all function refer to an element via a <type> *.
Each module knows its own structure, the structure of the other modules are not visible. In one module, I do not work with 1 element, but with a fixed array of elements. This means that some functions of that module work with a pointer to array.
Let's call that module wdi. So I have for example
void write_all(wdi_type (*wdis)[MAX_WDI]);
and for allocation (I know very unusual syntax) to return directly the right pointer to an array.
wdi_type (*wdi_alloc(void))[MAX_WDI];
This works well under GNU-C 3.4.6 (Solaris SPARC), under cc, the sun compiler v12 it compiles also (couldn't test it though because another part of the app breaks).
On gcc 4.3.3 (also tested on 4.4.6 x86-64 and 4.6.2 ARM) though, it doesn't. I get the compilation error array type has incomplete element type.
I don't understand why the compiler would need that information at that stage. It doesn't need the size of other opaque structures either.
Is it a gcc bug?
What does the standard say?
I wasn't able to find something about it. Should I file a bug report to GNU?
The standard (well, the N1570 draft of the C2011 standard) says, in 6.2.5 (20)
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified.
(emphasis by me)
The corresponding passage in the C99 standard was less forceful:
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.36)
36) Since object types do not include incomplete types, an array of incomplete type cannot be constructed.
it didn't explicitly forbid specifying an array type for an incomplete element type, only constructing such an array.
I haven't been able to find out when and why footnote 36 was replaced with the emphasised sentence, but it was before November 2010.
It would seem that gcc-4.x rejects the code based on the new version, while gcc-3.4.6 accepted it based on the older version, so I don't think it is a bug, and the code is explicitly invalid according to the current standard.

Resources