nonzero != 1, right?

T

Trent Buck

Could someone please confirm the following

A boolean expression, evaluates to true or false. In an integer
context, this becomes non-zero or zero, respectively.

Therefore the expression
x == y ? 0 : 1

CANNOT be abbreviated to
x == y

Thanks,
-trent
 
D

Dave Vandervies

Could someone please confirm the following

A boolean expression, evaluates to true or false. In an integer
context, this becomes non-zero or zero, respectively.

Therefore the expression
x == y ? 0 : 1

CANNOT be abbreviated to
x == y

All operators that return a boolean result are defined to return 0 or
1, so you can do this, or at least could if you didn't mind inverting
the result.
The correct abbreviation would be to `x != y', since your first expression
returns 0 if they're equal.

Note that this only applies to operators and not to the general case;
f'rexample, the isfoo function-or-macros in <ctype.h> are defined to
return nonzero, not necessarily one, as a "yes" value. An easy way
to fold zero-or-nonzero to zero-or-one is two applications of the
`!' operator ("!!val").


dave
 
J

Joona I Palaste

Trent Buck said:
Could someone please confirm the following
A boolean expression, evaluates to true or false. In an integer
context, this becomes non-zero or zero, respectively.
Therefore the expression
x == y ? 0 : 1
CANNOT be abbreviated to
x == y

There is a difference between treating an integer as a truth value and
vice versa. *Any* non-zero integer value means "true" when used as a
truth value, for example in "if (x)". However, boolean operators such
as "==", "!=", "<", etc. *always* return 1 and no other for "true" and
0 for "false". Therefore the expressions (x==y) and ((x==y)?1:0) are
synonymous. (You got the 0 and 1 wrong in your original expression
plus I'm not too sure about the precedence.)

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-------------------------------------------------------- rules! --------/
"'It can be easily shown that' means 'I saw a proof of this once (which I didn't
understand) which I can no longer remember'."
- A maths teacher
 
T

Trent Buck

Quoth Dave Vandervies on or about 2004-11-11:
All operators that return a boolean result are defined to return 0 or
1, so you can do this, or at least could if you didn't mind inverting
the result.

Thank you. And whoops, it's past my bedtime.
An easy way to fold zero-or-nonzero to zero-or-one is two applications
of the `!' operator ("!!val").

Yup. I've seen that in the canonical example of divide-and-round-up.

int
dru (int x, int y)
{
return x/y + !!(x%y);
}

....if I'm still awake.
 
A

Andrey Tarasevich

Trent said:
...
A boolean expression, evaluates to true or false.

In C language a "boolean" expression evaluates to 0 or 1. The result is
of type 'int'.
In an integer
context, this becomes non-zero or zero, respectively.

According to the above, it is always "in an integer context" and it is
always strictly 0 or 1.
Therefore the expression
x == y ? 0 : 1

CANNOT be abbreviated to
x == y
...

Well, it cannot be abbreviated this way simply because 'x == y'
evaluates to 1 if the values are the same, while the first variant
evaluates to 0.

If you meant 'x == y ? 1 : 0', then this CAN be abbreviated as 'x == y'.
 
K

Kenneth Brody

Dave Vandervies wrote:
[...]
All operators that return a boolean result are defined to return 0 or
1, so you can do this, or at least could if you didn't mind inverting
the result.
The correct abbreviation would be to `x != y', since your first expression
returns 0 if they're equal.
[...]

Note that, years ago, I worked on a system where boolean expressions
returned either 0 or -1. (I'm sure this is before ANSI stepped in and
said it must be 0 or 1.)

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
D

Dave Vandervies

Dave Vandervies wrote:
All operators that return a boolean result are defined to return 0 or
1, so you can do this, or at least could if you didn't mind inverting
the result.
The correct abbreviation would be to `x != y', since your first expression
returns 0 if they're equal.
[...]

Note that, years ago, I worked on a system where boolean expressions
returned either 0 or -1. (I'm sure this is before ANSI stepped in and
said it must be 0 or 1.)

That'd be all-bits-1 on a twos-complement system, I'm guessing?

That's also a reasonable "true" value, if it's consistent, or at least it
would be if it weren't in violation of the language definition. I seem
to recall that Commodore 64 BASIC did things this way (though I think
they also used zero for true and -1 (bitwise-not-of-true) for false).


dave
 
J

Joona I Palaste

Dave Vandervies said:
Dave Vandervies wrote:
All operators that return a boolean result are defined to return 0 or
1, so you can do this, or at least could if you didn't mind inverting
the result.
The correct abbreviation would be to `x != y', since your first expression
returns 0 if they're equal.
[...]

Note that, years ago, I worked on a system where boolean expressions
returned either 0 or -1. (I'm sure this is before ANSI stepped in and
said it must be 0 or 1.)
That'd be all-bits-1 on a twos-complement system, I'm guessing?
That's also a reasonable "true" value, if it's consistent, or at least it
would be if it weren't in violation of the language definition. I seem
to recall that Commodore 64 BASIC did things this way (though I think
they also used zero for true and -1 (bitwise-not-of-true) for false).

As a former Commodore 64 BASIC "bedroom programmer", I can definitely say
that Commodore 64 BASIC used 0 for false and -1 for true.
To be more specific, Commodore 64 BASIC and ISO standard C are exactly
alike in this respect - except! - the truth value "true" converted to an
integer is -1 in Commodore 64 BASIC instead of 1.
 
M

Malcolm

Trent Buck said:
Could someone please confirm the following

A boolean expression, evaluates to true or false. In an integer
context, this becomes non-zero or zero, respectively.

Therefore the expression
x == y ? 0 : 1

CANNOT be abbreviated to
x == y
Consider this

int xdoesntequaly(int x, int y)
{
return x - y;
}

Now we can use the value as a boolean

if( xdoesntequaly(1,1234))
{
printf("x doesn't equal y\n")
}

However

int xequalsy(int x, int y)
{
return ( x == y);
}

will always return 1 if x equals y, and 0 otherwise. So the expression x ==
y can here substitute for x == y ? 1 : 0;

However you would be really stupid to write code like that. The goal is to
make your code as clear as possible to read, not to save on keystrokes. So
returning an implict boolean isn't a good idea.
 
H

Horst Kraemer

Trent Buck said:
Could someone please confirm the following

A boolean expression, evaluates to true or false.

Any of the operators < > == != <= >= && || !

returns either 0 (to mean "false") or 1 (to mean "true"). Therefore an
expression where any of the above operators is the "top operator"
evaluates to either 0 or 1.
In an integer
context, this becomes non-zero or zero, respectively.

No. This _is_ already an integer with one of the values 0 or 1 in any
context.

You are confusing "outgoing" values and "incoming" values. "outgoing"
boolean results are always 0 or 1.

If an expression <E1> is used in

if(<E1>)
while(<E1>)
for (E0;E1;E2)
<E1>?:
<E1>||<E2>
<E1>&&<E2>
!<E1>


i.e. if some value is to be *interpreted* as a "boolean", then it is
considered as "false" if it compares equal to 0, otherwise as "true".

Therefore the meaning of is

if (<E1>) if (<E1>!=0)

etc.
 
M

Malcolm

pete said:
That's no good if x equals INT_MAX and y is negative.
The function returns true (non zero) if x != y, zero if x == y.

Consider a 16-bit twos complement machine. The argument is the same for 32
bits, but it is less typing.

INT_MAX = 0x7FFF;
y = -1.

x = y = 0x7FFF + 1 = 0x8000 = INT_MIN = non-zero, so we are OK.

A more interesting case is when one or both are INT_MIN.

INT_MIN is 0x8000
1s compelent INT_MIN is 0x7FFF
2s complement INT_MIN is 0x8000
ie -INT_MIN = INT_MIN !

however if x is not INT_MIN, x + 0x8000 is still non-zero, and INT_MAX is
one less than -INT_MIN.
However if x = INT_MIN

0x8000 + 0x8000 = |overflow bit| 0x0000, or false.

So we are still ok.

However you make a very good point, this is pretty hairy, and realistically
the function should always be writtem return x != y ? 1 : 0;

You may also be right for some very weird non-twos complement architectures,
but I doubt it, because using the subtraction operation to test for equality
is something that many processors do behind the scenes.
 
M

Michael Mair

Malcolm said:
pete said:
Malcolm wrote:



That's no good if x equals INT_MAX and y is negative.

The function returns true (non zero) if x != y, zero if x == y.

Consider a 16-bit twos complement machine. The argument is the same for 32
bits, but it is less typing.
[snip Example]
However you make a very good point, this is pretty hairy, and realistically
the function should always be writtem return x != y ? 1 : 0;

You may also be right for some very weird non-twos complement architectures,
but I doubt it, because using the subtraction operation to test for equality
is something that many processors do behind the scenes.

The standard says overflowing signed integers gives UB. Full stop.
However, you can just cast x and y to the corresponding unsigned
type and return an unsigned integer type; no problems with overflow
at all. If you want to return the signed type, you can use the !!
trick and obtain 1 and 0 as possible return values.

Cheers
Michael
 
P

pete

Michael said:
pete said:
Malcolm wrote:


Consider this

int xdoesntequaly(int x, int y)
{
return x - y;
}

That's no good if x equals INT_MAX and y is negative.

The function returns true (non zero) if x != y, zero if x == y.

Consider a 16-bit twos complement machine.
The argument is the same for 32
bits, but it is less typing.
[snip Example]
However you make a very good point, this is pretty hairy,
and realistically
the function should always be writtem return x != y ? 1 : 0;

I think
return x != y;
says it best.
The standard says overflowing signed integers gives UB. Full stop.

That's the point.
 
F

Flash Gordon

The function returns true (non zero) if x != y, zero if x == y.

Consider a 16-bit twos complement machine. The argument is the same
for 32 bits, but it is less typing.

The argument is the same for any integer size whether or not it is 2s
complement. The C standard says integer overflow is undefined behaviour,
so literally anything can happen.
INT_MAX = 0x7FFF;
y = -1.

x = y = 0x7FFF + 1 = 0x8000 = INT_MIN = non-zero, so we are OK.

Or you get an overflow exception causing the program to terminate. Or
you get a carry bit set that causes the next piece of arithmetic you do
to produce the result. Or you are using a processor that limits at
INT_MAX/INT_MIN (I've used C on one) and it is still INT_MAX which I
will admit does act as true.
A more interesting case is when one or both are INT_MIN.

INT_MIN is 0x8000
1s compelent INT_MIN is 0x7FFF
2s complement INT_MIN is 0x8000
ie -INT_MIN = INT_MIN !

Or an exception etc, see above.
however if x is not INT_MIN, x + 0x8000 is still non-zero, and
INT_MAX is one less than -INT_MIN.
However if x = INT_MIN

0x8000 + 0x8000 = |overflow bit| 0x0000, or false.

So we are still ok.

No you are not OK. Your program might have gone bang on overflow.
However you make a very good point, this is pretty hairy, and
realistically the function should always be writtem return x != y ? 1
: 0;

You may also be right for some very weird non-twos complement
architectures, but I doubt it, because using the subtraction operation
to test for equality is something that many processors do behind the
scenes.

It doesn't require a weird non-2s complement architecture. All it
requires is an architecture that provides an exception on integer
overflow.
 
M

Malcolm

Michael Mair said:
The standard says overflowing signed integers gives UB. Full stop.
However, you can just cast x and y to the corresponding unsigned
type and return an unsigned integer type; no problems with overflow
at all. If you want to return the signed type, you can use the !!
trick and obtain 1 and 0 as possible return values.
The whole point of the function was to return non-zero but not 1 for a true
condition.
However, yes, I should have remembered that overflows can cause traps,
though on most machines you will of course just get twos complement overflow
as described.
 
M

Michael Mair

Malcolm said:
The whole point of the function was to return non-zero but not 1 for a true
condition.

Sorry, I responded to your post. I did not read the whole thread
in order to do that.
Apart from that, if you want to return signed, then you can also
just take the result, say r, and return (signed)(r%a + r%b), a,b>1,
a+b<=INT_MAX+3U, gcd(a,b)>UINT_MAX, or whatever else you can
think of. I only reacted to the invoking of UB.

However, yes, I should have remembered that overflows can cause traps,
though on most machines you will of course just get twos complement overflow
as described.

Yep. UB can also do what you expect, as you know.
This was more for the sake of onlookers more innocent of C knowledge
than you are.

-Michael
 
L

Lawrence Kirby

On Sun, 14 Nov 2004 10:50:46 +0100, Michael Mair wrote:

....
The standard says overflowing signed integers gives UB. Full stop.
However, you can just cast x and y to the corresponding unsigned
type and return an unsigned integer type; no problems with overflow
at all.

But there is a different problem. The standard doesn't require that
UINT_MAX be larger than INT_MAX, they can be equal. In that case pairs of
signed int values (one positive one negative, and maybe INT_MIN,0) will
map to the same unsigned int result. This could result in the code
flagging numbers as equal when they are not.

Lawrence
 
M

Michael Mair

Lawrence said:
But there is a different problem. The standard doesn't require that
UINT_MAX be larger than INT_MAX, they can be equal. In that case pairs of
signed int values (one positive one negative, and maybe INT_MIN,0) will
map to the same unsigned int result. This could result in the code
flagging numbers as equal when they are not.

AFAIR, the standard requires that the standard unsigned integer types
use the full width, that the maximum value U*_MAX=2**width-1, that
the corresponding standard signed integer types use the same number of
bits, hence have a smaller maximal value.
Maybe there is something wrong with this reasoning but I think that
the C99 standard states it similar to the above.
Right now, I do not have the time to look it up but if you can prove
me wrong, feel welcome to do so as I would be interested where this
goes wrong :)
However, it would be sufficient that UINT_MAX<2*INT_MAX+1.


Cheers
Michael
 
L

Lawrence Kirby

AFAIR, the standard requires that the standard unsigned integer types
use the full width,

That is true for unsigned char, but for other unsigned types padding bits
are allowed. See e.g. C99 6.2.6.2p1
that the maximum value U*_MAX=2**width-1, that the corresponding
standard signed integer types use the same number of bits, hence have a
smaller maximal value.

The requirement on range is that C99 6.2.5p9:

"The range of nonnegative values of a signed integer type is a subrange of
the corresponding unsigned integer type, and the representation of the
same value in each type is the same."

So an implementation of unsigned types which is the same as the
corresponding signed type except that the sign bit is a padding bit is
valid, except for unsigned char.

There are minimum range limits e.g. UINT_MAX must be at least 65535. So if
unsigned int was 16 bits wide it would have to use all bits as value bits.
But a 32 bit wide one does not.

Lawrence
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top