Is thi me or GCC

N

Nick

I've just started to get a strange warning from GCC. Can you check my
code for me and check that this is GCC being silly - and so it should be
reported as a bug - not me missing something.

Here's a cut-down example:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *s;
char *a = "this is + some stuff";
for(s=a; s && *s; s && ++s) {
printf("[%c]",*s);
if(*s == '+')
s = NULL;
}
printf("\n");
return 0;
}

OK, not very elegant, but setting the pointer to null part way through
to abort the loop should work (I know I could use "break" - the real
example is more complicated).

It's that "s && ++s" in the third stanza of the for() that's causing the
problems. GCC complains "value computed is not used". That's true of
course, but the same is true of the traditional "++s". I can get round
it by casting that expression to void but surely I shouldn't need to do
this.

I see a few bug reports floating round of GCC being over-zealous with
this report in the latest version. So is my code fine, in which case
I'll complain about GCC, or should any decent compiler be complaining
about it (and in which case, for my education, why?)?
 
F

Flash Gordon

Nick said:
I've just started to get a strange warning from GCC. Can you check my
code for me and check that this is GCC being silly - and so it should be
reported as a bug - not me missing something.

Here's a cut-down example:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *s;
char *a = "this is + some stuff";
for(s=a; s && *s; s && ++s) {
printf("[%c]",*s);
if(*s == '+')
s = NULL;
}
printf("\n");
return 0;
}

OK, not very elegant, but setting the pointer to null part way through
to abort the loop should work (I know I could use "break" - the real
example is more complicated).

It's that "s && ++s" in the third stanza of the for() that's causing the
problems. GCC complains "value computed is not used". That's true of
course, but the same is true of the traditional "++s". I can get round
it by casting that expression to void but surely I shouldn't need to do
this.

Well, you *are* computing a value that you are not using!
I see a few bug reports floating round of GCC being over-zealous with
this report in the latest version. So is my code fine, in which case
I'll complain about GCC, or should any decent compiler be complaining
about it (and in which case, for my education, why?)?

It's a judgment call which is why the warning is not compulsory! You are
"calculating" a value which you are not using. It just happens that you
are not concerned with the value calculated.
 
S

Seebs

for(s=a; s && *s; s && ++s) {
It's that "s && ++s" in the third stanza of the for() that's causing the
problems. GCC complains "value computed is not used". That's true of
course, but the same is true of the traditional "++s". I can get round
it by casting that expression to void but surely I shouldn't need to do
this.

That is... odd.
I see a few bug reports floating round of GCC being over-zealous with
this report in the latest version. So is my code fine, in which case
I'll complain about GCC, or should any decent compiler be complaining
about it (and in which case, for my education, why?)?

Sure looks buggy to me. Hmm.

Just thinking about it, I suspect that this is being caused by the &&,
but it does seem like a bug in gcc.

-s
 
S

Seebs

Well, you *are* computing a value that you are not using!

Well, yes.
It's a judgment call which is why the warning is not compulsory! You are
"calculating" a value which you are not using. It just happens that you
are not concerned with the value calculated.

The thing is, a normal for loop does that too:
for (i = 0; i < 10; ++i)

So why does gcc warn about this? My guess is that they've special-cased
this partially, but when you write "s && s++", the compiler is confused;
it could understand disregarding the new value of s, and in any event
that value is used shortly later. But when you write "s && s++", you
compute another value -- 0 or 1 -- which is completely unused and not part
of the loop control.

It might be interesting to see whether such versions of gcc complain about:

int x = 0, i;
for (i = 0; x < 10; ++i) {
x++;
}

because the computed value of i is never used.

-s
 
F

Flash Gordon

Seebs said:
Well, yes.


The thing is, a normal for loop does that too:
for (i = 0; i < 10; ++i)

So why does gcc warn about this? My guess is that they've special-cased
this partially, but when you write "s && s++", the compiler is confused;
it could understand disregarding the new value of s, and in any event
that value is used shortly later. But when you write "s && s++", you
compute another value -- 0 or 1 -- which is completely unused and not part
of the loop control.

It might be interesting to see whether such versions of gcc complain about:

int x = 0, i;
for (i = 0; x < 10; ++i) {
x++;
}

because the computed value of i is never used.

I've never seen it warn in that case, and I think it is probable that
++/-- are special cased because it is so often used for the side effect
rather than for the return value.
 
J

James Dow Allen

That is... odd.

Well, ++s assigns to an lvalue.
(s && ++s) does that, *while creating*
a higher-level rvalue which gets discarded. But I
think gcc's decision of when to issue this "not used"
warning is probably based on an arbitrary heuristic
that isn't expected to be fool-proof.

For example, I think gcc complains on
(s && (s += 1))
but not
(s && (s = 1))

OP could change to the non-warning
(s += !!s)
But, although adding 0 is normally a do-nothing,
I'd check with the lawyers in case adding 0 to a
null pointer is somehow prohibited!

James
 
L

lawrence.jones

James Dow Allen said:
But, although adding 0 is normally a do-nothing,
I'd check with the lawyers in case adding 0 to a
null pointer is somehow prohibited!

It is. Most emphatically.
 
A

Alan Curry

Sure looks buggy to me. Hmm.

Just thinking about it, I suspect that this is being caused by the &&,
but it does seem like a bug in gcc.

Maybe it just thinks the result of a && expression shouldn't normally be
ignored. If you disagree, that's not a sign of a bug.

The lack of a warning for this version:

for(s=a; s && *s; s ? ++s : 0)

could be called a bug in the opposite direction, if you think that the
ternary operator's result also shouldn't be ignored.
 
B

Barry Schwarz

I wonder if the warning in the original posting was not about the ++
expression but about the && expression. The result of the original
expression is 0 or 1 (and a possible side effect) which is not used
anywhere.

Someone with gcc could test the two equivalent statements
++i;
and
1 && ++i;
or the almost equivalent but closer to the original code
i && ++i;
to determine what is driving gcc to produce the diagnostic in
question.
 
K

Keith Thompson

It is. Most emphatically.

Where "prohibited" means the behavior is undefined. Adding 0 to
a null pointer is likely to yield a null pointer on many, perhaps
most, implementations -- which just means that many, perhaps
most, implementations won't catch this bug for you.
 
B

Ben Bacarisse

Malcolm McLean said:
++s can never evaluate to false.

Rather, ++s can never be both well-defined and false. Since undefined
behaviour can be anything, when ++s is undefined its value can appear
to be false in every way that might matter to a program.
If s is NULL ++s is non-null, if s is 0xFFFF ++s is undefined.

If s is null, ++s is undefined. In that sense it might appear to be
non-null. As to the second half of your remark, it seems odd to pick
out one value. ++s is probably undefined for a very large set of
values for s.
So the expression is unused.

But that is not the kind of "not used" that gcc is complaining about.
For example, you get the same message if the last clause in the "for"
statement is, say, i && ++j where everything is well-defined.
 
P

Phil Carmody

Malcolm McLean said:
++s can never evaluate to false. If s is NULL ++s is non-null, if s is
0xFFFF ++s is undefined.

If s is NULL, ++s isn't even evaluated! If s is (char*)0xFFFF, then
++s may well be (char*)0x10000, and not undefined at all.
So the expression is unused.

It's clearly used for its side effects. The _value_ of the expression
may be unused, but that's true for many expresions, including most simple
assignments.

Phil
 
S

Seebs

what's the purpose of the 's && ++s' thingy?
Why not just write '++s'?

Because s might be set to null in the loop.

At which point:
1. It's undefined behavior to "++s".
2. If it did the most obvious thing, it would result in the loop control
ending up with a non-null pointer.

-s
 
F

Flash Gordon

Malcolm said:
Then you'd need more that 64000 bytes of memory installed. That's a lot of
values. What sort of equations do you calculate?


What are you talking about? All it needs in one byte of memory at
location 0xFFFF and more than 16 bits of address space. That covers
every PC I've used for the last 20+ years, and from memory of the OPs
post it looked more likely that it was a hosted system than an embedded one.
 
N

Nick

Robert Latest said:
what's the purpose of the 's && ++s' thingy?
Why not just write '++s'?

Have a look at the rest of the code - I set s to NULL under a particular
set of circumstances in order to terminate the loop early.

In real life, in that example, you'd just use a break, but consider -
for example - that there could be a switch on *s inside the loop and you want
to exit when it's a particular value. You can't use break in those
circumstances. You could use an auxiliary 'done' variable, of course.
But doing it this way is entirely legal, and not - I submit - something
a compiler ought (as distinct from "can"!) complain about.
 
P

Phil Carmody

Malcolm McLean said:
Then you'd need more that 64000 bytes of memory installed. That's a lot of
values. What sort of equations do you calculate?

Are you regressing into childhood, or something?
65535 became insignificant decades ago.

Phil
 
R

Robert Latest

Richard said:
Because otherwise it would crash ... Read the code.

Ah, I see. Because the third thingy in the for loop is done before
the test. Nice. Altough I avoid manipulating the loop variable -- either
by using break, or by having an additional flag variable that gets
tested in the for() line.

robert
 
D

Dik T. Winter

> for(s=a; s && *s; s && ++s) { ....
> It's that "s && ++s" in the third stanza of the for() that's causing the
> problems. GCC complains "value computed is not used". That's true of
> course, but the same is true of the traditional "++s".

Not really. In "++s" the computed value is assigned to s. In the original
the result of the logical and is not used.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top