I have made a structure for ints and pointers etc. as might be used in LISP.
A pointer is at least 8-byte aligned so tag=0.
An integer is 29 bits and has a tag of 1.
Other types have different tag values.
struct Atom{
union{
Pair *pair;
struct{
unsigned tag :3;
union{
int val :29;
char ch;
struct{
int mant :21;
Exp exp :8;
};
};
};
};
};
I would like to initialise them differently.
For pointers:
Atom aPair = {{.pair=0}}; // works
or
Atom aPair = {{0}}; //works
This works because, I assume, GCC assumes that I want to initialise the first member of the union.
I'd also like to initialise an integer - something like this:
Atom anInt={{ {.tag=1,{.val=0} } }};
I know this is not standard C, but is this possible at all with anonymous structures in GCC?
It is a known bug.
... which has been fixed in gcc 4.6 (using struct Atom anInt={{ .tag=1, {.val=0} }};).
Related
I'm trying to construct some C structs that themselves need to hold multiple structs. It looks something like this:
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
uint8_t f[];
} hdr_t;
typedef struct {
uint64_t data;
} pyld_t;
typedef struct {
hdr_t hdr;
pyld_t pyld;
} msg_t;
When I compile this, depending on the compiler and settings, I get warnings.
./file.h:55:24: warning: field 'hdr' with variable sized type 'hdr_t'
(aka 'struct hdr_t') not at the end of a struct or class is a GNU extension
[-Wgnu-variable-sized-type-not-at-end]
hdr_t hdr;
For this example, I'm using clang 6.1.0:
$ clang --version
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
The warning complain that what I'm doing is a non-portable GNU extension, which I'd rather avoid. What can I do to solve this? Is there not a safe way to put multiple structs in a struct? Surely that's not the case.
A C structure can be variable-size only in the sense that it may contain a "flexible array member" as its last member. C forbids such a structure type from being the type of any structure member or array element, though GCC permits that as an extension.
Even if GCC (or clang) accepted your declaration, I doubt it would mean what you think it means. Every member of a structure has a fixed offset relative to the beginning of the structure, determined statically at compile time. As a result, your msg_t cannot provide sufficient space for arbitrary hdr.f, and quite possibly it provides no space at all, especially if you enable structure packing. Thus, accessing hdr.f of a msg_t could easily access the message data, which I suppose is not what you expect.
I guess the whole point is to map a structure to a byte buffer, but if the underlying data format has variable-length elements in the middle then you just can't directly map a single C structure to it. You could, however, create and use an index structure:
typedef struct {
hdr_t *hdr;
pyld_t *pyld;
} msg_index_t;
That would make it easier to handle mapping a pair of structures to your buffer.
You could use an union:
typedef struct {
..stuff
}type_f1;
typedef struct {
..stuff
}type_f2;
typedef struct {
..stuff
}type_f3;
typedef union {
type_f1 f1;
type_f2 f2;
type_f3 f3;
uint8_t rawdata[MAX_RAWDATA];
}type_f;
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
type_f f;
} hdr_t;
typedef struct {
uint64_t data;
} pyld_t;
typedef struct {
hdr_t hdr;
pyld_t pyld;
} msg_t;
There's lots of solutions that will fix the issue. For my specific problem, just changing the declaration of hdr_t from this:
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
uint8_t f[];
} hdr_t;
to this:
typedef struct hdr_t {
uint16_t a;
uint16_t b;
uint8_t c;
uint8_t d[3];
uint64_t e;
uint8_t *f; //Use pointer instead of variable sized array
} hdr_t;
I'm not sure why the original code was using the array, but it wasn't necessary.
I'm taking over a piece of code..c programming in linux. I did a small change to a struct
typedef struct {
unsigned int a1;
..
..
..
float f1;
unsigned int a2;
unsigned int a3;
unsigned int offending; // shifted this
} test;
I shifted unsigned int offending to before float f1, like this:
typedef struct {
unsigned int a1;
..
..
..
unsigned int offending;
float f1;
unsigned int a2;
unsigned int a3;
} test;
and the code crashes... what could be the problem?
Is the order of members of a c struct important?
What could be the problem? Depend on the rest of the code, and what else you did.
No, the order of members of a struct is not intrinsically important. It is made so when other code depends on it.
Possible causes (not exhaustive):
You didn't recompile everything and there is external linkage on this struct or some aspect of it.
By moving the member you changed the alignment of other members and/or the sizeof() the struct, and didn't compensate for that.
There is a literal constant or macro somewhere with a size or offset that depends on this struct.
There is faulty code which never failed before but does now because of a change in memory layout.
The struct is used somewhere as part of another struct or union, and the problem is related to that.
There is a list initialisation using {} that no longer matches the member order.
You really should provide details of how it crashes. Otherwise it guesswork. And perhaps even then.
edit: ht #Jens.
The most probable reason for crashes if you change data layout is initialization. If you have old-time initializers in your code that use declaration order, all of a sudden the fields will receive different values than before. Therefore modern C since C99 has designated initializers that avoid that problem:
test toto = { 32, ... , 42, }; // sensible to reordering
test tata = { .a1 = 32, ... , .offending = 42, }; // still the same
I want the compiler to generate warning for me if structure declared without __attribute__(align(8)) .
For example, if a structure is declared like this:
struct my_float {
float number;
} __attribute__((aligned(8)));
It will not generate any warning. But if I declare another struct like this:
struct my_float {
float number;
};
the compiler will generate a warning for me.
My working enveronment is linux/GCC.
I don't think you can automatically check this an ALL your structure, but you still can check your alignment manually with something like:
// x % 16 <=> x & (16-1) (avoid using modulo operator)
#define MODULO_16_MASK 0xFU
ASSERT_COMPILE((sizeof(my_float) & MODULO_16_MASK) == 0);
This should trigger a warning at compiling if your structure is not aligned.
From experience, it is not possible to do.
This attribute specifies a minimum alignment (in bytes) for variables of the specified type.
struct S { short f[3]; } __attribute__ ((aligned (8)));
typedef int more_aligned_int __attribute__ ((aligned (8)));
force the compiler that each variable whose type is struct S or more_aligned_int is allocated and aligned at least on a 8-byte boundary.
C11 adds, among other things, 'Anonymous Structs and Unions'.
I poked around but could not find a clear explanation of when anonymous structs and unions would be useful. I ask because I don't completely understand what they are. I get that they are structs or unions without the name afterwards, but I have always (had to?) treat that as an error so I can only conceive a use for named structs.
Anonymous union inside structures are very useful in practice. Consider that you want to implement a discriminated sum type (or tagged union), an aggregate with a boolean and either a float or a char* (i.e. a string), depending upon the boolean flag. With C11 you should be able to code
typedef struct {
bool is_float;
union {
float f;
char* s;
};
} mychoice_t;
double as_float(mychoice_t* ch)
{
if (ch->is_float) return ch->f;
else return atof(ch->s);
}
With C99, you'll have to name the union, and code ch->u.f and ch->u.s which is less readable and more verbose.
Another way to implement some tagged union type is to use casts. The Ocaml runtime gives a lot of examples.
The SBCL implementation of Common Lisp does use some union to implement tagged union types. And GNU make also uses them.
A typical and real world use of anonymous structs and unions are to provide an alternative view to data. For example when implementing a 3D point type:
typedef struct {
union{
struct{
double x;
double y;
double z;
};
double raw[3];
};
}vec3d_t;
vec3d_t v;
v.x = 4.0;
v.raw[1] = 3.0; // Equivalent to v.y = 3.0
v.z = 2.0;
This is useful if you interface to code that expects a 3D vector as a pointer to three doubles. Instead of doing f(&v.x) which is ugly, you can do f(v.raw) which makes your intent clear.
struct bla {
struct { int a; int b; };
int c;
};
the type struct bla has a member of a C11 anonymous structure type.
struct { int a; int b; } has no tag and the object has no name: it is an anonymous structure type.
You can access the members of the anonymous structure this way:
struct bla myobject;
myobject.a = 1; // a is a member of the anonymous structure inside struct bla
myobject.b = 2; // same for b
myobject.c = 3; // c is a member of the structure struct bla
Another useful implementation is when you are dealing with rgba colors, since you might want access each color on its own or as a single int.
typedef struct {
union{
struct {uint8_t a, b, g, r;};
uint32_t val;
};
}Color;
Now you can access the individual rgba values or the entire value, with its highest byte being r. i.e:
int main(void)
{
Color x;
x.r = 0x11;
x.g = 0xAA;
x.b = 0xCC;
x.a = 0xFF;
printf("%X\n", x.val);
return 0;
}
Prints 11AACCFF
I'm not sure why C11 allows anonymous structures inside structures. But Linux uses it with a certain language extension:
/**
* struct blk_mq_ctx - State for a software queue facing the submitting CPUs
*/
struct blk_mq_ctx {
struct {
spinlock_t lock;
struct list_head rq_lists[HCTX_MAX_TYPES];
} ____cacheline_aligned_in_smp;
/* ... other fields without explicit alignment annotations ... */
} ____cacheline_aligned_in_smp;
I'm not sure if that example strictly necessary, except to make the intent clear.
EDIT: I found another similar pattern which is more clear-cut. The anonymous struct feature is used with this attribute:
#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
#define __randomize_layout __attribute__((randomize_layout))
#define __no_randomize_layout __attribute__((no_randomize_layout))
/* This anon struct can add padding, so only enable it under randstruct. */
#define randomized_struct_fields_start struct {
#define randomized_struct_fields_end } __randomize_layout;
#endif
I.e. a language extension / compiler plugin to randomize field order (ASLR-style exploit "hardening"):
struct kiocb {
struct file *ki_filp;
/* The 'ki_filp' pointer is shared in a union for aio */
randomized_struct_fields_start
loff_t ki_pos;
void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
void *private;
int ki_flags;
u16 ki_hint;
u16 ki_ioprio; /* See linux/ioprio.h */
unsigned int ki_cookie; /* for ->iopoll */
randomized_struct_fields_end
};
Well, if you declare variables from that struct only once in your code, why does it need a name?
struct {
int a;
struct {
int b;
int c;
} d;
} e,f;
And you can now write things like e.a,f.d.b,etc.
(I added the inner struct, because I think that this is one of the most usages of anonymous structs)
I am new to C and I want to know how to access elements inside a structure which is placed inside a structure.
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
How to access elements inside profile_t??
struct profile_t;
The above statement doesn't create an object of type profile_t. What you need to do is -
struct profile_t inObj ;
Then create object for profile_datagram_t. i.e.,
header outObj ; // header typedef for profile_datagram_t
Now you can access elements like -
outObj.inObj.type = 'a' ; // As an example
In C++, while creation of object for a structure, struct key word isn't necessary.
On your question edit and comment :
struct profile_t profiles[MAXPROFILES];
profiles is an array of objects of type profile_t. To access the individual object, just use the [] operator. i.e.,
header obj ;
obj.profiles[0].type = 'a' ; // Example
obj.profiles[i], where i can take values from 0 to MAXPROFILES - 1, gives the object at index i.
Not sure what happends in C, but in C++, rest of the stuff aside, the following declares two types.
struct profile_datagram_t
{
struct profile_t;
};
One type is named profile_datagram_t and the other is called profile_datagram_t::profile_t. The inner type declaration is just a forward declaration, so you'll need to define the type after.
struct profile_datagram_t::profile_t
{
// ...
};
Then, you can use the struct as follows:
int main ( int, char ** )
{
profile_datagram_t::profile_t profile;
}
Some compilers support a nonstandard extension to the C language (that I actually rather like, despite it being nonstandard) called anonymous structs (or unions). Code demonstration:
struct x {
int i;
};
struct y {
struct x;
};
int main(void)
{
struct y;
y.i = 1; // this accesses member i of the struct x nested in struct y
return 0;
}
In a nutshell, if you don't give the struct (or union) member a name, you can access its members directly from the containing struct (or union). This is useful in situations where you might have given it the name _, and had to do y._.i - the anonymous struct syntax is much simpler. However, it does mean that you have to remember the names of all members of both structs and ensure they never clash.
This is all, of course, a nonstandard extension, and should be used with caution. I believe it works on MSVC and can be enabled in GCC with a switch. Don't know about any other compilers. If you're worried about portability, give the member a proper name.
EDIT: According to the GCC reference (below) this behavior is being added to the upcoming C1X standard, so it won't be nonstandard for long. I doubt MSVC will support C1X since they refuse to support C99 as it is, but at least this feature is becoming part of the standard.
However, the behavior shown above is MSVC only. The C1X (and GCC without the -fms-extensions switch) syntax doesn't allow the unnamed struct member to have a name:
struct y {
struct {
int i;
};
};
int main(void) {
struct y;
y.i = 1; // this accesses member i of the struct x nested in struct y
return 0;
}
References for various compilers (they have different names but are the same concept):
GCC (unnamed fields): http://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html'
MSVC (anonymous structs): http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx
Basically you can use the following format:
variable = profile_t.element
profile_t.element = ?
EDIT: In your declaration of profile_datagram_t, the proper definition for struct profile_t should be:
struct profile_t someProfile;
Let's say you have:
header profileDiagram1;
struct profile_t profile1;
profileDiagram1.someProfile = profile1;
To access length, type or *data from profile_t:
profileDiagram1.someProfile.type;
profileDiagram1.someProfile.length;
...