This question already has answers here:
How to repair warning: missing braces around initializer?
(2 answers)
Closed 11 months ago.
I have this struct in C below that I want to initialize to all zero. How do I get rid of the missing braces warning?
typedef struct {
uint32_t incoming[FRAME_TYPE_MAX];
uint32_t outgoing[FRAME_TYPE_MAX];
uint32_t timeouts;
uint32_t crc_errors;
} pkt_t;
static pkt_t stats = {0};
This is GCC bug # 53119:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
If you want to see it fixed, post a followup to the bug report indicating that it's a problem for you.
Since your first member in the structure is an array you need:
static pkt_t stats = {{0}};
Outer braces are for the struct, inner braces are for the array. However, there are many other ways to skin this cat. (for instance, statics are already init'ed to zero)
If it is a global variable or a local static one, it's automatically initialized. So, simply:
static pkt_t stats;
One way is to initialize every member of the struct inside the braces, rather than relying on the implicit zero filling. For array members, you need another {} which is likely causing the warning. Another is to just disable the warning, though this isn't recommended as it can also catch legitimate bugs.
Set this gcc compiler flag:
-Wno-missing-braces
#define FRAME_TYPE_MAX 3
typedef struct {
uint32_t incoming[FRAME_TYPE_MAX];
uint32_t outgoing[FRAME_TYPE_MAX];
uint32_t timeouts;
uint32_t crc_errors;
} pkt_t;
static pkt_t stats1= { .incoming={5,6,20},
.outgoing={0,0,0},
.timeouts=0,
.crc_errors=0
};
static pkt_t stats2= { {5,6,20},
{0,0,0},
0,
0
};
static pkt_t stats3= {{0}};
pkt_t stats4 ; // global
int main(void)
{
stats1.incoming[0]= 35;
stats1.timeouts=25;
stats2.incoming[2]=10;
stats3.outgoing[2]=10;
stats4.timeouts=10;
for (;;);
}
If you still have the joy being on a gcc version which omits this false warning, with a struct like this in the question you can avoid this problem with some simple restructuring like this:
typedef struct {
uint32_t timeouts;
uint32_t crc_errors;
uint32_t incoming[FRAME_TYPE_MAX];
uint32_t outgoing[FRAME_TYPE_MAX];
} pkt_t;
static pkt_t stats = {0};
From "info gcc"
As a GNU extension, GCC allows initialization of objects with static storage duration by compound literals (which is not possible in ISO C99, because the initializer is not a constant). It is handled as if the object was initialized only with the bracket enclosed list if the types of the compound literal and the object match. The initializer list of the compound literal must be constant. If the object being initialized has array type of unknown size, the size is determined by compound literal size.
static struct foo x = (struct foo) {1, 'a', 'b'};
static int y[] = (int []) {1, 2, 3};
static int z[] = (int [3]) {1};
The above lines are equivalent to the following:
static struct foo x = {1, 'a', 'b'};
static int y[] = {1, 2, 3};
static int z[] = {1, 0, 0};
You may be able to combine these initializers to allow gcc-specific initialization of your arrays without having to specify every element in the array. Or...you can set a flag and initialize it at runtime when necessary, or...you can discover whether the variable is in BSS or not and may be automatically zeroed (is this on the stack in a function or in global memory).
Related
I have such two struct
struct table_element
{
struct table_val * table_val_arr;
int count_arr;
};
struct hash_table
{
struct table_element table_element_arr[MAX_NUMBER];
};
and here my test method
void test(struct hash_table * table)
{
int count;
struct table_element * tab_element;
for(count = 0; count < MAX_NUMBER; count++)
{
tab_element = &table->table_element_arr[count];
if(tab_element->table_val_arr == NULL)
{
printf("\nNULLLL!!!!!\n");
}
else
{
printf("\nOK!!!!!\n");
}
}
}
and here how I use it
int main(int argc, char **argv)
{
struct hash_table m_hash_table;
test(&m_hash_table);
...
I expect that all value would be NULL, but sometimes I get OK sometimes NULL...
What am I doing wrong?
How to init it with NULL?
Non-static variables defined inside of a function have indeterminate values if not explicitly initialized, meaning you can't rely on anything they may contain.
You can fix this by giving an initializer for the variable:
struct hash_table m_hash_table = {{NULL, 0},{NULL, 0},/*repeat MAX_NUMBER times*/};
Or by using memset:
memset(&m_hash_table, 0, sizeof(m_hash_table));
If you don't explicitly initialise a variable in C, it'll have an undefined value. eg.
int fish; // could be zero, -100, 3805, ...anything
int chips = 5; // will definitely be 5.
The same is true of pointers. They could point anywhere. And finally, the same is true of a structure's members.
There are two common approaches to this 'problem' depending on your needs.
memset the whole thing to zero:
struct hash_table m_hash_table;
memset( &m_hash_table, 0, sizeof(m_hash_table) );
Result: all the variables will be zero, all the pointers will be NULL1.
Explicitly set everything by hand:
struct hash_table m_hash_table;
for (int i = 0; i < MAX_NUMBER; i++)
{
m_hash_table.table_element_arr[i].table_val_arr = NULL;
m_hash_table.table_element_arr[i].count_arr = 0;
}
A third option is to provide initialisation when you declare the struct, but it's logically equivalent to option 2.
struct hash_table m_hash_table = { { NULL, 0 }, { NULL, 0 }, ... /*etc*/ };
1 As per the comments, it is true that there exist some architectures where a bit pattern of all zeros is not equivalent to NULL, and hence the memset( ..., 0, ...) approach is not strictly valid. However, for all practical purposes, on any modern platform, it's a perfectly valid, idiomatic solution.
(IMHO anyone using an architecture where this isn't true isn't going to be looking for advice on SO about how to initialise their structures!)
You declared m_hash_table as an automatic variable. Such variables are usually located on the stack. The stack space may be filled with random content.
You have three options.
Declare it as a static variable: static struct hash_table m_hash_table;
Use memset(): memset(&m_hash_table, 0, sizeof(m_hash_table));
Use explicit initializer: struct hash_table m_hash_table = {};
UPDATE#1
According to this http://c-faq.com/null/machexamp.html information options #1 and #2 do not work correctly on some hardware. The option #3 gives the desired result.
UPDATE#2
The discussion below reveals a new truth. Option #1 is the best.
The struct hash_table m_hash_table; is automatic storage, (vs say, static, in which case it would be automatically initialised.) This means the contents of the variable are indeterminate. One could initialise it several ways, see initialisation, (or the other answers.) However, I think that this is important to know that memset is not a proper way to initialise a null pointer, (the C FAQ has an entire section on null pointers.) Like Pascal's nil or Java's null, 0 in pointer context has a special meaning in C, the null pointer. It commonly is all-bits-zero, leading to the mistaken impression that 0 is actually all-bits-zero, but this is not always the case. The general idiomatic way is to have a constructor in which you set any null pointers with explicit,
te->table_val_arr = 0; /* or NULL. */
te->count_arr = 0;
Edit: three initialisations are shown:
#include <stddef.h>
#include <assert.h>
/* `struct table_val` is undefined in this limited context. */
struct table_element {
int * table_val_arr;
int count_arr;
};
/** `te` is a value that gets initialised to be empty. */
static void table_element(struct table_element *const te) {
assert(te);
te->table_val_arr = 0; /* Or `NULL`, depending on your style. */
te->count_arr = 0;
}
struct hash_table {
struct table_element table_element_arr[100];
};
static size_t hash_table_size =
sizeof ((struct hash_table *)0)->table_element_arr
/ sizeof *((struct hash_table *)0)->table_element_arr;
/** `ht` is a value that gets initialised to be empty. */
static void hash_table(struct hash_table *const ht) {
size_t i;
assert(ht);
for(i = 0; i < hash_table_size; i++)
table_element(ht->table_element_arr + i);
}
/* This is automatically initialised to all-elements-zero, (which is not
necessary all-bits-zero.) */
static struct hash_table g_hash_table;
int main(void) {
struct hash_table m_hash_table = {{{0,0}}}; /* Initialiser. */
struct hash_table table; /* Garbage. */
hash_table(&table); /* Now fixed. */
return 0;
}
The dynamic way of using constructor functions is scalable to large objects and objects that one doesn't want to necessarily initialise with zero; C++ expands this greatly to RAII. The initialisation in the declaration is limited to constant expressions, and thus is probably the most efficient. The static option changes the storage class of the object and is probably unsuitable except for objects that one wanted to declare static anyway.
A colleague (not on SO) has suggested this answer: Partially initializing a C struct
Which says (in essence) if you initialise the first element of your structure, the compiler will automatically initialise everything else to zero or NULL (as appropriate) for you.
Copying from that...
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
—if it has pointer type, it is initialized to a null pointer;
—if it has arithmetic type, it is initialized to (positive or unsigned) zero;
—if it is an aggregate, every member is initialized (recursively) according to these rules;
—if it is a union, the first named member is initialized (recursively) according to these rules.
...
21 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.
I have been trying something in structures in C.
struct val{
unsigned int a : 1 ;
}store[100] ;
Now I want to initialize all the array members value to 1. That is, I want all the array members to have their variable a assigned to 1. I can use a loop for that but how can I do this during the declaration?
struct val
{
unsigned int a=1 : 1 ;
}store[100];
How can i achieve this? The above syntax is coming out to be wrong in code::blocks.
struct val
{
unsigned int a : 1;
}store[100];
I initially thought that what you were doing was a bitfield initialization. Further research though suggested I am wrong, and that you are trying to use gcc's designated initializers. What you want to do, is not possible that way. I found another way in your code that you can do it, though:
typedef struct {
unsigned int a;
} val;
then, where you want to initialize the array, you will do something like that:
val values[100] = {[0].a = 1};
This works by exploiting this behavior of gcc:
If the same field is initialized multiple times, it has the value from the last initialization. If any such overridden initialization has side-effect, it is unspecified whether the side-effect happens or not. Currently, GCC discards them and issues a warning.
My Test Program follows:
#include <stdio.h>
struct val {
unsigned int a;
};
int
main (void)
{
struct val value[100] = {[0].a = 1};
printf ("A random val's value is %d\n", value[40].a);
return 0;
}
Compiles and works cleanly on my GCC 4.9.1.
It's not possible.
You can use a loop, or, if by any chance you want to initialize all struct's data members to a specific value, you can also use memset:
struct val {
unsigned int a : 1 ;
} store[N];
memset(store, value, N * sizeof(struct val));
Before declaring a struct variable you can't initialize its member. Initialization can be done as
struct val{
unsigned int a : 1;
}store[100] = {[0].a = 1} ; // Designated initializer
but it will initialize a member of other elements of store to 0. To initialize member a of all elements of store you need a loop.
I have a simple structure that is defined like so:
typedef struct {
int index;
double* arrayToRead;
} my_struct;
I want to initialize an array of structures so they become something like this:
double decimals[2] = {1.0, 2.0};
my_struct[2] = {
{0, &decimals[0]},
{1, &decimals[1]}
};
I have to initialize this array of structs statically.
Can I initialize it statically while referring to a previously defined member, like so:
my_struct[2] = {
{0, &decimals[index]},
{1, &decimals[index]}
};
Where "index" refers to the value for index defined to the left of "decimals"?
If you have a modern C compiler (aka C99) you can use P99 for code unrolling. Something like
#define INIT_ELEMENT(NAME, X, I) [I] = { \
.index = I, \
.arraytoread = &decimals[I] \
}
#define INIT_ELEMENTS(N) P99_FOR(, N, P00_SEQ, INIT_ELEMENT, P99_DUPL(N,))
and then
my_struct A[] = { INIT_ELEMENTS(2) };
should expand to an initializer of your liking.
(Here the first macro defines the code that is to be repeated, using only I from its arguments, the index of the invocation. In the second macro P00_SEQ means that this is separated by comma.)
No.*
If you're desperate, you could always devise a macro for this purpose:
#define DEFINE_ELEMENT(i) {(i), &decimals[(i)]}
my_struct m[2] = {
DEFINE_ELEMENT(0),
DEFINE_ELEMENT(1)
};
#undef DEFINE_ELEMENT
* Or "yes", as #Jens points out in his answer, for C99.
What's that in the sky? It's a bird! No, it's a plane! No, it's Code-Generation Man!
Or--with tongue removed from cheek--I don't know that there is a built in feature that supports this, but you can always use an external tool to write the initialization code for you.
Basically you write a script in some convenient language that output a c code fragment defining the structure and declaring the variable with the long-hand intialization, then use the c-preprocessor's #include feature to drag that generated file into you code.
You'll want to make the build manager aware of this need. In make it would look something like
cfile.o: cfile.c mystruct.c
my_struct.c:
awk -f generate_my_struct.awk > my_struct.c
i think that you need to give a name for your new array
my_struct my_array[2] = {
{0, &decimals[my_array[0].index]},
{1, &decimals[my_array[1].index]}
};
I'm trying to create structs with default values. I don't know how to accomplish this because every code that I see, is about initialising, and I would it for the natural way like...
struct stuff {
int stuff_a = 1;
int stuff_b = 2...
...and so on...
};
and looking about, I found this (C++) code:
struct a{ a() : i(0), j(0) {}; INT i; INT j;}
I never saw anything like this for C. Please, help me to understand it; I think that it is very nice!
UPDATE: Wait, I'm asking about C!!!! Why changed my question? If that is not possible in C just say... I don't know C++, I didn't know that was about C++...
If you want to set a struct object in one go and you have a C99 compiler, try this:
struct stuff {
int stuff_a;
int stuff_b;
// and so on...
};
struct stuff foo;
/* ... code ... */
foo = (struct stuff){.stuff_b = 42, .stuff_a = -1000};
Otherwise, with a C89 compiler, you have to set each member one by one:
foo.stuff_b = 42;
foo.stuff_a = -1000;
Running example # ideone : http://ideone.com/1QqCB
The original line
struct a{ a() : i(0), j(0) {} INT i; INT j;}
is a syntax error in C.
As you have probably learned from the other answers, in C you can't declare a structure and initialize it's members at the same time. These are different tasks and must be done separately.
There are a few options for initializing member variables of a struct. I'll show a couple of ways below. Right now, let's assume the following struct is defined in the beginning of the file:
struct stuff {
int stuff_a;
int stuff_b;
};
Then on your main() code, imagine that you want to declare a new variable of this type:
struct stuff custom_var;
This is the moment where you must initialize the structure. Seriously, I mean you really really must! Even if you don't want to assign specific values to them, you must at least initialize them to zero. This is mandatory because the OS doesn't guarantee that it will give you a clean memory space to run your application on. Therefore, always initialize your variables to some value (usually 0), including the other default types, such as char, int, float, double, etc...
One way to initialize our struct to zero is through memset():
memset(&custom_var, 0, sizeof(struct stuff));
Another is accessing each member individually:
custom_var.stuff_a = 0;
custom_var.stuff_b = 0;
A third option, which might confuse beginners is when they see the initialization of struct members being done at the moment of the declaration:
struct stuff custom_var = { 1, 2 };
The code above is equivalent to:
struct stuff custom_var;
custom_var.stuff_a = 1;
custom_var.stuff_b = 2;
... create structs with default values ...
That is impossible in C. A type cannot have default values. Objects of any type cannot have a default value other than 0, though they can be initialized to whatever is wanted.
The definition of a struct is a definition of a type, not of an object.
What you asking is about the same thing as a way to have ints default to, say, 42.
/* WRONG CODE -- THIS DOES NOT WORK */
typedef int int42 = 42;
int42 a;
printf("%d\n", a); /* print 42 */
Or, adapting to your example
/* WRONG CODE -- THIS DOES NOT WORK */
struct stuff {
int42 stuff_a;
int65536 stuff_b;
}
struct stuff a;
printf("%d\n", a.stuff_b); /* print 65536 */
Update: This answer assumes we 're talking about C++ because the code posted in the answer is not legal C.
struct a {
a() : i(0), j(0) {} // constructor with initialization list
int i;
int j;
}
The line marked with the comment is simply the constructor for instances of struct a (reminder: structs are just like classes, except that the default member visibility is public instead of private).
The part after the : is called an initialization list: it allows you to initialize the members of the struct with values (either constants or passed as constructor parameters). Initialization of members in this list happens before the body of the constructor is entered. It is preferable to initialize members of classes and structs this way, if at all possible.
See also C++: Constructor versus initializer list in struct/class.
in C (pre C99) the following also works:
#include <stdio.h>
typedef struct
{
int a;
int b;
int c;
} HELLO;
int main()
{
HELLO a = {1,2,3};
printf("here: %d %d %d\n",a.a,a.b,a.c);
exit(1);
}
See codepad
I'm not sure quite sure what your problem is. The standard way of initialising structures in c is like this:
struct a_struct my_struct = {1, 2};
Or the more recent and safer:
struct a_struct my_struct = {.i1 = 1, .i2 = 2};
If there is more than one instance of a structure, or it needs to be re-initialised, it is useful to define a constant structure with default values then assign that.
typedef struct a_struct {
int i1;
int i2;
} sa;
static const sa default_sa = {.i1 = 1, .i2 = 2};
static sa sa1 = default_sa;
static sa sa2 = default_sa;
// obviously you can do it dynamically as well
void use_temp_sa(void)
{
sa temp_sa = default_sa;
temp_sa.i2 = 3;
do_something_with(&temp_sa);
}
// And re-initialise
void reset_sa(sa *my_sa)
{
*my_sa = default_sa;
}
Type initializer is not possible in C.
A value must be stored in the memory.
A type does not occupy memory, what occupies memory is a variable of that type.
struct stuff; is a type; it does not occupy memory
struct stuff aStuff; is a variable of that type; aStuff occupies memory
Because a type does not occupy memory, it is not possible to save values into a type.
If there is syntactic sugar to support store/initialize values into a type then there must be additional code that is inserted to assign values to every instant variables of that type (e.g: in constructor in C++). This will result in a less efficient C if this feature is available.
How often do you need to retain this default values? I think it is unlikely. You can create a function to initialize variable with the default values or just initialize every fields with the values you want. So type initializer is not fundamental thing. C is about simplicity.
Can't initialize values within a structure definition.
I'd suggest:
typedef struct {
int stuff_a;
int stuff_b;
} stuff ;
int stuffInit(int a, int b, stuff *this){
this->stuff_a = a;
this->stuff_b = b;
return 0; /*or an error code, or sometimes '*this', per taste.*/
}
int main(void){
stuff myStuff;
stuffInit(1, 2, &myStuff);
/* dynamic is more commonly seen */
stuff *dynamicStuff;
dynamicStuff = malloc(sizeof(stuff)); /* 'new' stuff */
stuffInit(0, 0, dynamicStuff);
free(dynamicStuff); /* 'delete' stuff */
return 0;
}
Before the days of Object Oriented Programming (C++), we were taught "Abstract Data Types".
The discipline said 'never access your data structures directly, always create a function for it' But this was only enforced by the programmer, instructor, or senior developer, not the language.
Eventually, the structure definition(s) and corresponding functions end up in their own file & header, linked in later, further encapsulating the design.
But those days are gone and replaced with 'Class' and 'Constructor' OOP terminology.
"It's all the same, only the names have changed" - Bon Jovi.
Why can't we initialize members inside a structure ?
example:
struct s {
int i = 10;
};
If you want to initialize non-static members in struct declaration:
In C++ (not C), structs are almost synonymous to classes and can have members initialized in the constructor.
struct s {
int i;
s(): i(10)
{
}
};
If you want to initialize an instance:
In C or C++:
struct s {
int i;
};
...
struct s s_instance = { 10 };
C99 also has a feature called designated initializers:
struct s {
int i;
};
...
struct s s_instance = {
.i = 10,
};
There is also a GNU C extension which is very similar to C99 designated initializers, but it's better to use something more portable:
struct s s_instance = {
i: 10,
};
The direct answer is because the structure definition declares a type and not a variable that can be initialized. Your example is:
struct s { int i=10; };
This does not declare any variable - it defines a type. To declare a variable, you would add a name between the } and the ;, and then you would initialize it afterwards:
struct s { int i; } t = { 10 };
As Checkers noted, in C99, you can also use designated initializers (which is a wonderful improvement -- one day, C will catch up with the other features that Fortran 66 had for data initialization, primarily repeating initializers a specifiable number of times). With this simple structure, there is no benefit. If you have a structure with, say, 20 members and only needed to initialize one of them (say because you have a flag that indicates that the rest of the structure is, or is not, initialized), it is more useful:
struct s { int i; } t = { .i = 10 };
This notation can also be used to initialize unions, to choose which element of the union is initialized.
Note that in C++ 11, the following declaration is now allowed:
struct s {
int i = 10;
};
This is an old question, but it ranks high in Google and might as well be clarified.
Edit2: This answer was written in 2008 and relates to C++98. The rules for member initialization have changed in subsequent versions of the language.
Edit: The question was originally tagged c++ but the poster said it's regarding c so I re-tagged the question, I'm leaving the answer though...
In C++ a struct is just a class which defaults for public rather than private for members and inheritance.
C++ only allows static const integral members to be initialized inline, other members must be initialized in the constructor, or if the struct is a POD in an initialization list (when declaring the variable).
struct bad {
static int answer = 42; // Error! not const
const char* question = "what is life?"; // Error! not const or integral
};
struct good {
static const int answer = 42; // OK
const char* question;
good()
: question("what is life?") // initialization list
{ }
};
struct pod { // plain old data
int answer;
const char* question;
};
pod p = { 42, "what is life?" };
We can't initialize because when we declared any structure than actually what we do, just inform compiler about their presence i.e no memory allocated for that and if we initialize member with no memory for that. Normally what happens when we initialize any variable that depends on the place where we declared variable compiler allocate memory for that variable.
int a = 10;
if it's auto than in stack memory going to allocate
if it's global than in data sections memory going to allocate
So what memory is required to hold that data but in case of structure no memory is there so not possible to initialize it.
As you said it's just a member not a variable. When you declare a variable the compiler will also provide memory space for those variables where you can put values. In the case a of a struct member the compiler is not giving memory space for it, so you cannot assign values to struct members unless you create a variable of that struct type.