473,320 Members | 1,876 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Conditional operator using void expression

I have run across functions in the Linux kernel's MTD driver that have
me scratching my head a bit. The functions have the general form:

extern int bar(size_t len, size_t *retlen, unsigned char *buf);

int foo(size_t len, unsigned char *buf) {
size_t retlen;
int ret;

ret = bar(len, &retlen, buf);
return ret ? : retlen; /* <-- void expression and UB? */
}

It is foo()'s return statement that I am soliciting comments about. Am
I correct that the conditional operator's second operand is a void
expression and if so, doesn't that invoke undefined behavior by
attempting to use the value of a void expression? I sometimes
struggle interpreting the standard and hope I haven't overlooked
something, but I can't find the verse that might bless the statement.
If it is allowed, what value would foo() return for nonzero ret --
zero?

Thanks,

--
Dan Henry
Feb 27 '07 #1
15 5167
Dan Henry wrote:
I have run across functions in the Linux kernel's MTD driver that have
me scratching my head a bit. The functions have the general form:

extern int bar(size_t len, size_t *retlen, unsigned char *buf);

int foo(size_t len, unsigned char *buf) {
size_t retlen;
int ret;

ret = bar(len, &retlen, buf);
return ret ? : retlen; /* <-- void expression and UB? */
}

It is foo()'s return statement that I am soliciting comments about. Am
I correct that the conditional operator's second operand is a void
expression and if so, doesn't that invoke undefined behavior by
attempting to use the value of a void expression? I sometimes
struggle interpreting the standard and hope I haven't overlooked
something, but I can't find the verse that might bless the statement.
If it is allowed, what value would foo() return for nonzero ret --
zero?
I think it's a syntax error, but gcc accepts it without complaint in
default mode. It does warn in strict mode:

gcc -Wall -pedantic -ansi x.c
x.c: In function `foo':
x.c:11: warning: ISO C forbids omitting the middle term of a ?: expression

I guess Linux kernel hackers don't use strict mode :)

--
Ian Collins.
Feb 27 '07 #2
Dan Henry <us****@danlhenry.comwrites:
I have run across functions in the Linux kernel's MTD driver that have
me scratching my head a bit. The functions have the general form:

extern int bar(size_t len, size_t *retlen, unsigned char *buf);

int foo(size_t len, unsigned char *buf) {
size_t retlen;
int ret;

ret = bar(len, &retlen, buf);
return ret ? : retlen; /* <-- void expression and UB? */
}

It is foo()'s return statement that I am soliciting comments about. Am
I correct that the conditional operator's second operand is a void
expression and if so, doesn't that invoke undefined behavior by
attempting to use the value of a void expression?
[...]

No, it's not a void expression. A void expression would be an
expression of type void, such as (void)42. What appears between the
'?' and ':' is an empty token sequence, and is not an expression at
all. As far as standard C is concerned, it's simply a syntax error.

As an extension, gcc allows the middle operand of the conditional
operator to be omitted; see the gcc documentation for details. This
is a permissible extension, since it doesn't affect the behavior of
any strictly conforming program.

gcc with the "-pedantic" option correctly issues a warning for this.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Feb 27 '07 #3
On Feb 26, 7:34 pm, Dan Henry <use...@danlhenry.comwrote:
I have run across functions in the Linux kernel's MTD driver that have
me scratching my head a bit. The functions have the general form:

extern int bar(size_t len, size_t *retlen, unsigned char *buf);

int foo(size_t len, unsigned char *buf) {
size_t retlen;
int ret;

ret = bar(len, &retlen, buf);
return ret ? : retlen; /* <-- void expression and UB? */

}

It is foo()'s return statement that I am soliciting comments about. Am
I correct that the conditional operator's second operand is a void
expression and if so, doesn't that invoke undefined behavior by
attempting to use the value of a void expression?
It's not a void expression, it's the lack of an expression. It isn't
valid Standard C but is a gcc extension in which:
x ? : y;
is treated as:
x ? x : y;

It's a useful extension but it isn't Standard.

Robert Gamble
Feb 27 '07 #4

Dan Henry wrote:
I have run across functions in the Linux kernel's MTD driver that have
me scratching my head a bit. The functions have the general form:

extern int bar(size_t len, size_t *retlen, unsigned char *buf);

int foo(size_t len, unsigned char *buf) {
size_t retlen;
int ret;

ret = bar(len, &retlen, buf);
return ret ? : retlen; /* <-- void expression and UB? */
}

It is foo()'s return statement that I am soliciting comments about. Am
I correct that the conditional operator's second operand is a void
expression and if so, doesn't that invoke undefined behavior by
attempting to use the value of a void expression? I sometimes
struggle interpreting the standard and hope I haven't overlooked
something, but I can't find the verse that might bless the statement.
If it is allowed, what value would foo() return for nonzero ret --
zero?

Thanks,
In general the Linux kernel makes unapolegetic use of gcc's
extensions, of which this is one. It a form of shortcut that evaluates
to:

return ret ? ret : retlen;

Feb 27 '07 #5
Robert Gamble wrote:
On Feb 26, 7:34 pm, Dan Henry <use...@danlhenry.comwrote:
.... snip ...
> return ret ? : retlen; /* <-- void expression and UB? */

It is foo()'s return statement that I am soliciting comments
about. Am I correct that the conditional operator's second
operand is a void expression and if so, doesn't that invoke
undefined behavior by attempting to use the value of a void
expression?

It's not a void expression, it's the lack of an expression. It
isn't valid Standard C but is a gcc extension in which:
x ? : y;
is treated as:
x ? x : y;

It's a useful extension but it isn't Standard.
As far as I am concerned, using it is extremely sloppy programming
when portable programming would only require one extra identifier.
It's all very well to use extensions when they actually help, but
stupid when they are unnecessary.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Feb 27 '07 #6
On Mon, 26 Feb 2007 16:53:22 -0800, Keith Thompson <ks***@mib.org>
wrote:
>Dan Henry <us****@danlhenry.comwrites:
>I have run across functions in the Linux kernel's MTD driver that have
me scratching my head a bit. The functions have the general form:

extern int bar(size_t len, size_t *retlen, unsigned char *buf);

int foo(size_t len, unsigned char *buf) {
size_t retlen;
int ret;

ret = bar(len, &retlen, buf);
return ret ? : retlen; /* <-- void expression and UB? */
}

It is foo()'s return statement that I am soliciting comments about. Am
I correct that the conditional operator's second operand is a void
expression and if so, doesn't that invoke undefined behavior by
attempting to use the value of a void expression?
[...]

No, it's not a void expression. A void expression would be an
expression of type void, such as (void)42. What appears between the
'?' and ':' is an empty token sequence, and is not an expression at
all. As far as standard C is concerned, it's simply a syntax error.

As an extension, gcc allows the middle operand of the conditional
operator to be omitted; see the gcc documentation for details. This
is a permissible extension, since it doesn't affect the behavior of
any strictly conforming program.

gcc with the "-pedantic" option correctly issues a warning for this.
Ian, Keith, Robert, and santosh:

Thank you all for your gentle guidance. I am not often fooled by
GCC-isms, but that *gratuitous* extension caught me thinking that I
had missed some corner-case of language usage.

I have emphasized *gratuitous* above because, in my opinion, that
extension (if limited to that bit of functionality, and I'll be
looking it up tomorrow to see if it is that limited) offers very
little or perhaps even negative benefit if one factors in the cost of
having to think about it even being an extension -- but that's just
me.

[Ranting OT rhetorical question]
I can appreciate some GCC-isms in the context of "the kernel" easing
some things, but really now, is eliminating/shorthanding the second
operand *that* useful?
[/Ranting OT rhetorical question]

--
Dan Henry
Feb 27 '07 #7
Man, you guys are brutal! "obdurate" is the word of the day that comes to
mind... How often does a "legit" post come along?

"CBFalconer" <cb********@yahoo.comwrote in message
news:45***************@yahoo.com...
Robert Gamble wrote:
>On Feb 26, 7:34 pm, Dan Henry <use...@danlhenry.comwrote:
... snip ...
>> return ret ? : retlen; /* <-- void expression and UB? */

It is foo()'s return statement that I am soliciting comments
about. Am I correct that the conditional operator's second
operand is a void expression and if so, doesn't that invoke
undefined behavior by attempting to use the value of a void
expression?

It's not a void expression, it's the lack of an expression. It
isn't valid Standard C but is a gcc extension in which:
x ? : y;
is treated as:
x ? x : y;

It's a useful extension but it isn't Standard.

As far as I am concerned, using it is extremely sloppy programming
when portable programming would only require one extra identifier.
It's all very well to use extensions when they actually help, but
stupid when they are unnecessary.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>


Feb 27 '07 #8
Mike King wrote:

[top-post fixed]
"CBFalconer" <cb********@yahoo.comwrote in message
news:45***************@yahoo.com...
Robert Gamble wrote:
On Feb 26, 7:34 pm, Dan Henry <use...@danlhenry.comwrote:
... snip ...
> return ret ? : retlen; /* <-- void expression and UB? */

It is foo()'s return statement that I am soliciting comments
about. Am I correct that the conditional operator's second
operand is a void expression and if so, doesn't that invoke
undefined behavior by attempting to use the value of a void
expression?

It's not a void expression, it's the lack of an expression. It
isn't valid Standard C but is a gcc extension in which:
x ? : y;
is treated as:
x ? x : y;

It's a useful extension but it isn't Standard.
As far as I am concerned, using it is extremely sloppy programming
when portable programming would only require one extra identifier.
It's all very well to use extensions when they actually help, but
stupid when they are unnecessary.
Man, you guys are brutal! "obdurate" is the word of the day that comes to
mind... How often does a "legit" post come along?
As far as I can see, nobody is criticising the OP for his genuine
mistake. Also I should probably warn you that you'll shortly be
advised not to top-post.

Feb 27 '07 #9
Dan Henry <us****@danlhenry.comwrites:
[...]
Thank you all for your gentle guidance. I am not often fooled by
GCC-isms, but that *gratuitous* extension caught me thinking that I
had missed some corner-case of language usage.

I have emphasized *gratuitous* above because, in my opinion, that
extension (if limited to that bit of functionality, and I'll be
looking it up tomorrow to see if it is that limited) offers very
little or perhaps even negative benefit if one factors in the cost of
having to think about it even being an extension -- but that's just
me.

[Ranting OT rhetorical question]
I can appreciate some GCC-isms in the context of "the kernel" easing
some things, but really now, is eliminating/shorthanding the second
operand *that* useful?
[/Ranting OT rhetorical question]
Quoting the gcc documentation:

In this simple case, the ability to omit the middle operand is not
especially useful. When it becomes useful is when the first
operand does, or may (if it is a macro argument), contain a side
effect. Then repeating the operand in the middle would perform
the side effect twice. Omitting the middle operand uses the value
already computed without the undesirable effects of recomputing
it.

I'm not necessarily arguing that the Linux kernel *should* use this
particular extension, but since the decision has already been made to
use gcc-specific features (to the extent that compiling the kernel
with anything other than gcc is nearly impossible), I suppose it's
just a matter of the kernel being written in GNU-C rather than C.

(I think Intel's icc can also compile the kernel, but a lot of effort
has been put into making it gcc-compatible.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Feb 27 '07 #10
On Mon, 26 Feb 2007 23:26:15 -0600, "Mike King" <wm***@cox.netwrote:
>Man, you guys are brutal! "obdurate" is the word of the day that comes to
mind... How often does a "legit" post come along?
Admonishing sloppy programming, which is arguably what the OP's
example constituted, should not be labeled "obdurate". Just as
admonishing top-posting should not be labeled "obdurate" (awkward
context as a result of your top-posting follows).
>"CBFalconer" <cb********@yahoo.comwrote in message
[snip]
>As far as I am concerned, using it is extremely sloppy programming
when portable programming would only require one extra identifier.
It's all very well to use extensions when they actually help, but
stupid when they are unnecessary.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Feb 27 '07 #11
santosh wrote, On 27/02/07 06:27:
Mike King wrote:

[top-post fixed]
>"CBFalconer" <cb********@yahoo.comwrote in message
news:45***************@yahoo.com...
>>Robert Gamble wrote:
On Feb 26, 7:34 pm, Dan Henry <use...@danlhenry.comwrote:
<snip discussion of what turnout out to be a gcc extension>
>>>It's a useful extension but it isn't Standard.
As far as I am concerned, using it is extremely sloppy programming
when portable programming would only require one extra identifier.
It's all very well to use extensions when they actually help, but
stupid when they are unnecessary.
Man, you guys are brutal! "obdurate" is the word of the day that comes to
mind... How often does a "legit" post come along?
The OPs posts have been "legit". The OP asked about something he thought
must be standard C, and this is the right place for that, and has
accepted the the expert advice that it is not standard C. The OP even
went on to express an opinion about the use of such extensions that I
believe many of the regulars here (including me) would agree with.
As far as I can see, nobody is criticising the OP for his genuine
mistake.
I would say that the OPs mistake in assuming it was standard C was
entirely understandable so I think it unlikely that the OP will be
criticised by those it is worth reading here.
Also I should probably warn you that you'll shortly be
advised not to top-post.
OK, we can't have you being mistaken about such a thing.

Mike, please don't top post, your reply belongs after (or interspersed
with the text you are replying to. See most of the posts in this group
for examples including the one you were replying to.
--
Flash Gordon
Feb 27 '07 #12
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>Quoting the gcc documentation:

In this simple case, the ability to omit the middle operand is not
especially useful. When it becomes useful is when the first
operand does, or may (if it is a macro argument), contain a side
effect. Then repeating the operand in the middle would perform
the side effect twice. Omitting the middle operand uses the value
already computed without the undesirable effects of recomputing
it.
I don't find this very convincing. The usual reason for macros of this
kind is efficiency, and the usual reason for using them rather than
inline functions is portability to systems that don't provide them.
Since GCC does support inline functions, using a different GCC-specific
mechanism is pointless.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Feb 27 '07 #13
Mike King wrote:
Man, you guys are brutal! "obdurate" is the word of the day that comes to
mind...
It happens, nevermind.
How often does a "legit" post come along?
Not very often. Usually when it is "how do I return
a char array from function" or similar. And you
better don't top-post here, it's dangerous, can invoke
undefined behavior of some regulars.

[snip essay about sloppiness and happiness]

Best regards,
Yevgen
Feb 27 '07 #14
Richard Tobin wrote:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>Quoting the gcc documentation:

In this simple case, the ability to omit the middle operand is not
especially useful. When it becomes useful is when the first
operand does, or may (if it is a macro argument), contain a side
effect. Then repeating the operand in the middle would perform
the side effect twice. Omitting the middle operand uses the value
already computed without the undesirable effects of recomputing
it.

I don't find this very convincing. The usual reason for macros of this
kind is efficiency, and the usual reason for using them rather than
inline functions is portability to systems that don't provide them.
Since GCC does support inline functions, using a different GCC-specific
mechanism is pointless.
return foo() ? : bar;

It's not only about macros. Of course one always can introduce
a helper variable here and everything (of course one can use
standard C), that's another thing.

Yevgen
Feb 27 '07 #15
Yevgen Muntyan <mu****************@tamu.eduwrites:
Richard Tobin wrote:
>In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>>Quoting the gcc documentation:

In this simple case, the ability to omit the middle operand is not
especially useful. When it becomes useful is when the first
operand does, or may (if it is a macro argument), contain a side
effect. Then repeating the operand in the middle would perform
the side effect twice. Omitting the middle operand uses the value
already computed without the undesirable effects of recomputing
it.
I don't find this very convincing. The usual reason for macros of
this
kind is efficiency, and the usual reason for using them rather than
inline functions is portability to systems that don't provide them.
Since GCC does support inline functions, using a different GCC-specific
mechanism is pointless.

return foo() ? : bar;

It's not only about macros. Of course one always can introduce
a helper variable here and everything (of course one can use
standard C), that's another thing.
Yes, that's a good example. If the ability to omit the middle operand
were specified in the standard, I wouldn't hesitate to use the
feature. It's not a critical feature, in that there are easy ways to
avoid it, but it is a nice notational convenience once you understand
how it works. If I'd been voting on features to add to the language,
I probably would have picked this one before allowing trailing commas
in enumerations.

I'm not advocating adding this to the standard; I wouldn't mind if it
were added, but I understand the dangers of creeping featurism. (And
if it were added to C200Y, or C201Z, it would be many years before we
could count on it being universally implemented.) But if you're
writing code that's absolutely dependent on a specific compiler and
its extensions, you might as well use them.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Feb 27 '07 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: TheKeith | last post by:
I just wrote the following script for something I'm working on: ---------------------------------------------------------------------------- ------------------- <html> <head> <script...
6
by: Mahesh Tomar | last post by:
Please see the code below :- void func() { unsigned char x,y,z=1; (z==1) ? (x) : (y) = 1; /* Compiles OK */ ((z==1) ? (x) : (y)) = 1; /* Compiler generates an error "Variable expected" */ }
4
by: mux | last post by:
Hi I found out that the following piece of code throws an error. 1 #include "stdio.h" 2 3 int main() 4 { 5 int a,b; 6 a= 10;
6
by: Chris Dunaway | last post by:
Consider this code (.Net 2.0) which uses a nullable type: private void button1_Click(object sender, System.EventArgs e) { DateTime? nullableDate; nullableDate = (condition) ? null :...
10
by: Jonathan | last post by:
Hi all, I'm having an argument with a co-worker about the difference between the & and && operators when applied to boolean operands in C#. His point of view is that the expression (false &...
11
by: junky_fellow | last post by:
Hi guys, I have a piece of code: int func(int flag) { int number=1; if (flag == 1) return 0; if(flag == 2)
5
by: paulo | last post by:
Can anyone please tell me how the C language interprets the following code: #include <stdio.h> int main(void) { int a = 1; int b = 10; int x = 3;
4
by: Colin J. Williams | last post by:
It would be helpful if the rules of the game were spelled out more clearly. The conditional expression is defined as X if C else Y. We don't know the precedence of the "if" operator. From the...
15
by: Nicholas M. Makin | last post by:
I was just thinking that I understood the conditional operator when I coded the following expecting it to fail: int a= 10, b= 20, c= 0; ((a < b) ? a : b) = c; // a=0 a=20; b= 10; ((a < b) ? a...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.