Reputation: 21
From "21st Century C" example 10.8
typedef struct {
double width, height;
} size_s;
size_s width_height(char *papertype){
return
!strcasecmp(papertype, "A4") ? (size_s) {.width=210, .height=297}
: !strcasecmp(papertype, "Letter") ? (size_s) {.width=216, .height=279}
: !strcasecmp(papertype, "Legal") ? (size_s) {.width=216, .height=356}
: (size_s) {.width=NAN, .height=NAN};
}
Trying to use this style in WINAVR with GCC
(a_t_g.value.ax > xx) ?
{ leds |= rpr; //roll positive red
leds &= ~rpa; //clear amber
flag |= flagrdd; //set the flag for any red
}
: (a_t_g.value.ax < -xx) ?
{ leds |= rnr; //roll negative red
leds &= ~rna; //clear amber
flag |= flagrdd; //set the flag for any red
}
:{}
This results in error: expected expression before '{' token
.
Can GCC not handle this or am I doing something wrong? How does one handle the final do nothing in this style?
Upvotes: 0
Views: 353
Reputation: 21
Thank you all for the replies. It is now clear to me, and I have learned. After reading the book, I wanted to try something like the example. I then took some if..else working code and substituted the conditional operator. Also I was curious if the else part could be ignored. Apparently not. I was not aware of the GCC extension. The author was quoting C99. Sure, everybody knows the if..else, but on the other hand, the author's code provides a neat table, and is C99 safe. When the use of protothreads limits the use of the switch statement, this would be another tool to use. Knowledge was gained. Thank you
Upvotes: 0
Reputation: 241671
The code cited includes this:
return ... ? (size_s) {.width=210, .height=297} ! ...
That is not the "statement expression" GCC extension. It is a C99 designated-initializer, which creates an instance of a size_s
with its width
and height
members initialized to 210 and 297, respectively. (Had there been other members in the struct
, they would have been initialized to 0.) The explicit cast (size_s)
is required, because it would be impossible to guess the type of the object the initializer is being applied to. That's a perfectly legal syntax which all C99 compilers must recognize.
That's not at all "the same style" as
(a_t_g.value.ax > xx) ? { leds |= rpr; ... } : {}
This is an attempt to use the GCC "statement expression" extension. However, that extension requires that the braced-block be surround with parentheses, so the "correct" way to write it would be:
(a_t_g.value.ax > xx) ? ({ leds |= rpr; ... }) ... : ({});
GCC won't complain about that, although many other compilers would. Unless you know that no-one will ever try compiling your code will with a compiler other than GCC -- which is a dangerous assumption -- you should avoid GCC extensions, particularly in cases like this where the value of the ternary operator is ignored -- making it possible to use ({})
, whose type is void
. This code would be more elegant and readable if it were just written in the normal way as an if
statement.
Upvotes: 2
Reputation: 1385
?:
operator doesn't support blocks which returns nothing, so you have to return something in your code.
(a_t_g.value.ax > xx) ?
({ leds |= rpr; //roll positive red
leds &= ~rpa; //clear amber
flag |= flagrdd; //set the flag for any red
})
: (a_t_g.value.ax < -xx) ?
({ leds |= rnr; //roll negative red
leds &= ~rna; //clear amber
flag |= flagrdd; //set the flag for any red
})
:({})
You can use()
around the blocks like I have used in the above code to make this code to work.
Upvotes: 2
Reputation: 8614
The format of a conditional operator is
condition? value_if_true : value_if_false;
What the original format is, looks like
condition ? value1 : condition2 ? value2 : condition3 ? value3 : last_value;
In your expression, you are missing the :last_value
part.
You need to relook at your expression to add this value.
Upvotes: -1
Reputation: 361555
The ternary ?:
operator is for use in expressions. Both branches need to be an expression with a value; it doesn't make sense to have an empty block. Note that using compound blocks in expressions is a GCC extension, one which there's no reason to be using here.
The way to get this to work is to use plain if
and else
.
if (a_t_g.value.ax > xx) {
leds |= rpr; //roll positive red
leds &= ~rpa; //clear amber
flag |= flagrdd; //set the flag for any red
}
else if (a_t_g.value.ax < -xx) {
leds |= rnr; //roll negative red
leds &= ~rna; //clear amber
flag |= flagrdd; //set the flag for any red
}
Upvotes: 4