C Struct initialization : strange way - c

While reading a code I came across, the following definition and initialization of a struct:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt __foo = {
.name = "NAME";
.value = some_value;
}
What does this mean in C and how is it different from usual declarations?

It's called designated initialization,
In a structure initializer, specify
the name of a field to initialize with
.fieldname = before the element
value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
If you read on, it explains that .fieldname is called a designator.
UPDATE: I'm no C99 expert, but I couldn't compile the code. Here's the changes I had to make:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
//struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt = {
.name = "NAME",
.value = 123
};
Were you able to compile it? I used TCC.

Those are designated initializers, introduced in c99. You can read more here
Without them, you'd use
struct foo fooElmnt __foo = {
"NAME",
some_value
};
While in this case it doesn't matter much - other than the c99 way is more verbose, and its easier to read which element is initialized to what.
It does help if your struct has a lot of members and you only need to initialize a few of them to something other than zero.

This is a designated initialization. This also initializing the fields by their name, which is more readable than anomynous initialization when the structures are getting large. This has been introduced by the C99 standard.

Related

How to find all assignment expressions of a certain type

Say I have some struct definition like
struct sql_subtype {
sql_type *type;
unsigned int digits;
unsigned int scale;
}
This struct sql_subtype is used all over the place in my codebase which is huge. Objects of this type are often members of other objects. So simple string matching is not good enough to find the assignment locations. Is there some nice trick or open source static-analysis tool that can give me the locations in the code base where any object of this type is being set to some value? Find all locations similar to
struct sql_subtype type1 = type2;
or
c1->t = c2->t; // where the t's are of the type of interest.
etc.
The general problem: given the class of expressions that involve a certain operator that returns a certain type, how can I find all statements that contain expressions of this class?
Not a general solution, but there is a way to find the struct assignments with the C compiler alone. C allows you to declare members of struct as const, so you can add an extra member to the struct that is declared as const and only assignments will fail:
struct sql_subtype {
unsigned int digits;
unsigned int scale;
const unsigned int poison_pill;
};
void function_call(struct sql_subtype foo) {
struct sql_subtype initialized_from_copy = foo;
initialized_from_copy.digits = 42;
struct sql_subtype another = {0};
another = foo;
}
// if the const member is the last one even initializer lists will work!
struct sql_subtype initialized = {1, 2};
int main(void) {
function_call(initialized);
}
compile with GCC, and the only diagnostics you get are
constmemberhack.c: In function ‘function_call’:
constmemberhack.c:10:13: error: assignment of read-only variable ‘another’
another = foo;
^

Referencing a struct within a struct

I have a C struct generated by an external tool. It looks like this:
typedef struct externalStruct{
int msgID;
struct internalStruct {
long someValue;
} *internalStruct ;
} externalStruct_t;
Do the following leaves internalStruct pointed to some random value on the heap:
externalStruct_t* newExternalStruct = new externalStruct_t;
So here's my question:
How do I properly instantiate the pointer "internalStruct"?
Here is how you can do it in C (C99 demo):
externalStruct_t* newExternalStruct = malloc(sizeof(externalStruct_t));
newExternalStruct->internalStruct = malloc(sizeof(*newExternalStruct->internalStruct));
In C++ you would need to insert casts (C++ demo):
externalStruct_t* newExternalStruct = new externalStruct_t;
// You need to rename internalStruct to internalStructType
// to avoid a naming collision:
newExternalStruct->internalStruct = new externalStruct::internalStructType;

Error: initializer element is not constant - linux driver

I am really not able to solve this issue.
error: initializer element is not constant
error: (near initialization for tca6507_leds1.leds.num_leds)
I think the problem is related to struct led_info *leds inside led_platform_data. Is this somehow not a const since it is a pointer? I am particularly baffled since led_platform_data and led_info are part of the linux kernel. tca6507_platform_data is also a part of a driver that is included in the kernel source.
Here is my initialization:
static struct led_info tca6507_led_infos[] = {
{
.name = "left_blue",
.default_trigger = "heartbeat",
},
};
static struct led_platform_data tca6507_leds2 = {
.leds = tca6507_led_infos,
};
struct tca6507_platform_data tca6507_leds1 = {
.leds = tca6507_leds1
};
All the structs are defined in header files that I did not write.
struct led_info {
const char *name;
const char *default_trigger;
int flags;
};
struct led_platform_data {
int num_leds;
struct led_info *leds;
};
struct tca6507_platform_data {
struct led_platform_data leds;
#ifdef CONFIG_GPIOLIB
int gpio_base;
void (*setup)(unsigned gpio_base, unsigned ngpio);
#endif
};
The problem is right in the middle of this three line bit:
struct tca6507_platform_data tca6507_leds1 = {
.leds = tca6507_leds1
};
What is the (compile time) value of tca6507_leds1? Note that it is a structure, not an array.
Compare that with the (valid):
static struct led_platform_data tca6507_leds2 = {
.leds = tca6507_led_infos,
};
What is the (compile time) value of tca6507_led_infos? (Note that it is an array, and the "value" of an array is the address of its first element.) And most importantly (perhaps I should not have buried the lede :-) ), compare with the (also valid):
static struct led_info tca6507_led_infos[] = {
{
.name = "left_blue",
.default_trigger = "heartbeat",
},
};
Note that instead of using the value of a variable, the initializer here is a brace-enclosed list of items. This (like the failing case) is an instance of struct led_info, which must contain one actual struct led_platform_data instance (not a pointer to one-or-more, as is used in struct led_platform_data).
(The above is meant as an exercise. The answer is, the value of a structure is the value of the structure—but that is not a compile-time constant. Moreover, you are trying to use the value of the structure that you have not yet finished initializing in the first place. You need X to set X but you have to find X first, which you do by finding X, and there's no end to the recursion.)

What does a dot before the variable name in struct mean?

looking at the linux kernel source, I found this:
static struct tty_operations serial_ops = {
.open = tiny_open,
.close = tiny_close,
.write = tiny_write,
.write_room = tiny_write_room,
.set_termios = tiny_set_termios,
};
I've never seen such a notation in C.
Why is there a dot before the variable name?
This is a Designated Initializer, which is syntax added for C99.
Relevant excerpt:
In a structure initializer, specify the name of a field to initialize
with ‘.fieldname =’ before the element value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
It's sometimes called "designated initialization". This is a C99 addition, though it's been a GNU extension for a while.
In the list, each . names a member of the struct to initialize, the so called designator.

Constructor for structs in C

Given:
struct objStruct {
int id;
int value;
};
typedef struct objStruct Object;
Is there a shortcut to allocate and initialize the object, something like a C++ constructor?
It could even be a preprocessor macro. Whatever makes the code shorter and more readable than this:
Object *newObj = malloc(sizeof(Object));
// successful allocation test snipped
newObj->id = id++;
newObj->value = myValue;
In C I typically create a function in the style of a constructor which does this. For example (error checking omitted for brevity)
Object* Object_new(int id, int value) {
Object* p = malloc(sizeof(Object));
p->id = id;
p->value = value;
return p;
}
...
Object* p1 = Object_new(id++, myValue);
In C99 and beyond, you can use a compound literal, which looks like a cast followed by an initializer in braces:
int init_value = ...;
int init_id = ...;
Object newObj1 = (Object){ .value = init_value, .id = init_id };
Object newObj2 = (Object){ .id = init_id, .value = init_value };
The latter two lines achieve the same effect - the order of the fields is not critical. That is using 'designated initializers', another C99 feature. You can create a compound literal without using designated initializers.
In C it is possible to declare an inline function with the same name as structure:
struct my
{
int a;
};
inline struct my* my(int* a)
{
return (struct my*)(a);
}
//somewhere in code
int num = 123;
struct my *sample = my(&num);
//somewhere in code
It looks pretty similar to C++ ctors.
struct thingy {
char * label;
int x;
};
#define declare_thingy( name, label, val) struct thingy name = { label, val }
struct thingy * new_thingy(const char * label, int val) {
struct thingy * p = malloc(sizeof(struct thingy));
if (p) {
p->label = label;
p->val = val;
}
return p;
}
You really have to distinguish initialization of static or auto variables and dynamic allocation on the head. For the first, do named initializers, for the second a well specified init function.
All that can be nicely
packed into macros do give you an easy static/auto intialization and something similar to new in C++.
If you are looking for an object oriented "emulation" over C, I strongly recommend the GObject Type System [1], it's mature and largely used by GTK for instance.
GLib [2] has also a nice slice allocator for small objects, currently used by GNOME.
[1] GObject Reference Manual
[2] GLib Memory Slices

Resources