here is my code
typedef struct{
double x;
double y; } point;
typedef struct{
int hour;
int minute;
int second;
} time;
typedef struct{
point position;
time interval;} record;
record r[3] = {{{{1},{1}}, {{1},{1},{0}}}, {{{2},{1}}, {{1},{1},{1}}}, {{{2},{2}}, {{1},{1},{2}}}};
I think I used the correct syntax, but I tried removing the outer brackets too
CodePudding user response:
Indent and comment your initialization properly to see the problem. The innermost braces around the scalar values, i.e. around the single numbers, are wrong.
If it's not all in one line, the compiler can better show you where exactly the problem is.
GCC even adds note: (near initialization for ‘r[0].position.x’)
and similar messages for all scalar values (double
or int
in your case).
typedef struct{
double x;
double y; } point;
typedef struct{
int hour;
int minute;
int second;
} time;
typedef struct{
point position;
time interval;} record;
record r[3] =
{ // r
{ // r[0]
{ // r[0].position
{ // r0.position.x --> this brace is wrong
1.0 // make clear this is a double instead of an int here
},
{ // r0.position.y --> this brace is wrong
1.0
}
},
{ // r[0].interval
{1},
{1},
{0}
}
},
{
// etc
{{2},{1}}, {{1},{1},{1}}}, {{{2},{2}}, {{1},{1},{2}}}};
You could also use tagged initialization if supported by your compiler or your chosen C standard. This is even better than comments because the compiler can check the tags for errors in contrast to pissibly wrong comments.
record r[3] = {
[0] = {
.position = {
.x = 1.0,
.y = 1.0
}
.interval = {
.hour = 1,
.minute = 1,
.second = 0
}
},
[1] = {
// etc
{{2},{1}}, {{1},{1},{1}}}, {{{2},{2}}, {{1},{1},{2}}
}
};
CodePudding user response:
To comment on "braces around scalar initializer", it means that you are doing initialization similar to
int x = {1};
where int x = 1;
would suffice. The former is actually valid C, but pointless and confusing, possibly a mistake, so I suppose the message you got was an informative warning.
C uses formal terms to group variable types. Scalar refers to all arithmetic and pointer types where you simply have one item of something. As opposed to aggregate which refers to arrays and structs.
When initializating aggregates, there are various intricate rules that allows one to skip braces around initializers in certain cases. But doing so is also bad practice since it can lead to subtle bugs. Compilers tend to warn against that as well.
I would strongly recommend to be explicit when performing initialization. And use empty lines so that your initialization list resembles the structs rather than a completely unreadable "one-liner".
In this case you could instead have written:
record r[3] =
{
{
.position = { .x = 1.0, .y = 1.0 },
.interval = { /* ... */}
},
{
.position={ /* and so on... */
},
};
This way of initialization is known as designated initializers and makes the code a lot easier to read when dealing with more complex structs.