Is there a way to design a macro that could ensure an element is at the start of a struct during it's definition? For example:
typedef struct {
START(int a);
} b;
// Becomes
typedef struct {
int a;
} b;
But generate a compiletime error when it isn't the first element?
typedef struct {
int c;
START(int a);
} b;
// Generate an error
I was thinking you could use a combo of the OFFSETOF and BUILD_BUG_ON_ZERO macros but this would require knowing the struct layout while initializing it, and produces an error because the variable is undeclared.
Is this possible in C?
Use a compile time assertion at the locations you actually assume that layout, instead of at the definition site. Of course you will need to actually define it at the start in order to pass the assertion.
Perhaps something like this would work for you:
#define typedef_header(x) typedef struct { x
typedef_header(int a);
int c;
} b;
int main()
{
b x;
}
Related
Is there a way of knowing the type of a struct member at compile time? Something analogous to offsetof(), but for types.
Eg. something like:
typedef struct{
int b;
char c;
}a_t;
typeof(a_t,b) a_get_b(void* data){
return *(typeof(a_t,b)*)(data + offsetof(a_t,b));
}
If you're willing to use typeof (which is currently a very common nonstandard C extension slated for inclusion in the next version of the standard), you can apply it to a member obtained from a compound literal as in typeof((a_t){0}.b):
typedef struct{ int b; char c; }a_t;
typeof((a_t){0}.b) a_get_b(void* data){ return (a_t*){data}->b; }
(Given a type a_t, (a_t){0} is a reliable way to get an instance of it. Because of how initialization works in C, the 0 will initialize a deepest first elementary member and elementary types are scalars and therefore 0-initializable.)
As for the obtaining the member from a void pointer pointing to the container, you could do:
*(typeof(&(a_t){0}.b)((char*)data + offsetof(a_t,b))
but that's just an awfully long-winded way to do:
(a_t*){data}->b
(which is 100% equivalent to the former as long as the effective type of data is indeed a_t*).
Another way it works:
#include <stdio.h>
#define typeof_element(_struct,el) typeof(((_struct *)(0))->el)
typedef struct{
int a;
int b;
}Row;
int main()
{
typeof_element(Row, a) value_a = 10;
printf("%d\n", value_a);
return 0;
}
Another way (other than Jerry Jeremiah's) is:
#define struct_get(STRUCT,ELEM) *(typeof(STRUCT.ELEM)*) (STRUCT+offsetof(typeof(STRUCT),ELEM))
Hi I was triying to make something like this, but I cant sort it out. The problem is one typedef needs the other one. I would really appreciate someones help!
#ifndef SHELL_DATA_H
#define SHELL_DATA_H
#include <buffer.h>
#define COMMANDS 10
#define MAX_ARGS 4
typedef struct {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
} t_command;
typedef struct {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
} t_shellData;
#endif
typedef struct command t_command;
typedef struct shelldata t_shellData;
struct command {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
};
struct shelldata {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
};
should fix it up for you. The structure tag and typedef name can be the same; I just renamed them for clarity.
C is a simple language, with an underlying principle of do not surprise people. For this reason, entities in C need to be declared or defined before they are used. As a simple example:
int f() {
int a = 7;
int b = a;
....
}
is OK, but this is not:
int f() {
int b = a;
int a = 7;
....
}
and while not exactly, languages like golang permit this -- the compiler will root around and find the definition you obviously wanted.
Typedef, in C, really just puts an entry into the symbol table; it is like a define, but less blunt, so the line:
typedef struct a A;
Serves to inform the compiler of two things: somewhere there is a structure with tag a, and I want A to be a shortform for it. There is another form of this:
struct a;
typedef struct a A;
Here, the first line tells the compiler "I want you to know about a thing called struct a"; and the second line "I want an alias to that struct a thing called A".
So, as the compiler progresses through the source, it knows that an A means a struct a, and even if it hasn't seen the definition of struct a, it has a placeholder.
But, if you attempted, before defining struct a to define another structure:
struct b {
struct a stuff;
int morestuff;
};
The compiler would complain, because it doesn't know the layout of a struct a; however this:
struct b {
struct a *stuff;
int morestuff;
};
is OK, because it knows how big a pointer is, and can defer its understanding of a struct a until it needs it.
So, Summary: declare or define data types before you attempt to use them. The C compiler requires it. A declaration is ok, unless you need the actual layout of it, in which case a definition is required.
Good Luck.
I have a struct that might have 2 or 4 members depending on a preprocessor definition.
struct foo {
int m1;
int m2;
#ifdef MORE_MEMBERS
int m3;
int m4;
#endif
}
I have functions that take foo.m3 and foo.m4 as arguments. Because of that, I get a compilation error when MORE_MEMBERS isn't defined.
I'm trying to avoid adding #ifdef at every function call. Is there some way to make m3 and m4 be aliases/dummies when MORE_MEMBERS isn't defined? I'd like to still keep the struct size equal to sizeof(int) * 2.
I agree with Iharob, it's horrible code. It's not too clear what you're after, but it sounds like you could use a union:
struct foo
{
int a;
int b;
};
union bar
{
struct foo m1m2;
struct foo m3m4;
};
void f(union bar *x)
{
printf("%d", x->m1m2.a);
printf("%d", x->m3m4.b);
}
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 */
I have 2 headers that need to define 2 similar structures. One structure should be aligned to 32bytes and other is similar but doesn't need to align to 32bytes so I can save some memory here. One is included in the other. Here is main_header.h
struct mainStruct
{
int a;
int b;
int c;
char pad[20];
};
Following is sub_header.h
#include "main_header.h"
struct subStruct
{
int a;
int b;
int c;
};
Now what I wish to do is define subStruct in a way that, whenever i change mainStruct other than pad[20] all other fields should be updated in subStruct. That is, if tomorrow, I make mainStruct like this:
struct mainStruct
{
int a;
int b;
int c;
int d;
char pad[16];
};
then, automatically it should be reflected in sub_header.h as
struct subStruct
{
int a;
int b;
int c;
int d;
};
Is there an efficient way of doing it using some kind of Macros or other preprocessor directives??
And subStruct should always be derived from mainStruct and not other way around, this is very important.
Thanks in advance.
Did you consider the other way around; including subStruct as an element in mainStruct? Like this:
struct sub {
int a, b, c;
};
struct main {
struct sub head;
char dummy[16];
};
True, it does take an extra layer of syntax to get at a, b or c, but the memory layout and performance should be the same.
Otherwise, there's nothing preventing you from using a macro, as you suggest yourself:
#define SUB_FIELDS int a; int b; int c;
struct main {
SUB_FIELDS
char dummy[16];
};
struct sub {
SUB_FIELDS
};
Well, that's why C++ was initially invented. But if you wish to stay with plain C (there could be reasons for such decision) you may check GLib / GObject type system implemented as a set of macros over plain C.