Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   warning: comparison is always true due to limited range of data type (http://www.velocityreviews.com/forums/t703009-warning-comparison-is-always-true-due-to-limited-range-of-data-type.html)

phil-news-nospam@ipal.net 10-26-2009 06:27 PM

warning: comparison is always true due to limited range of data type
 
I have the following expression coded in a macro:

((((__typeof__((x)))0) - ((__typeof__((x)))1)) < ((__typeof__((x)))0))

It uses GCC's extension __typeof__() but I don't think that's an issue.
This expression is intended to evaluate true whenever x is a signed integer
and false whenever x is an unsigned integer. The purpose is to give the
compiler a good chance at optimizing out the expressions that follow in the
?: trinary operator. Since this expression is strictly a constant, it should
be easy to detect that only one or the other of the ?: expressions is needed.

When I use int, long, or long long, either signed or unsigned, this compiles
without any warning. When I use signed short, it is also without warning.
But when I use unsigned short, I get the warning.

Clearly, the result will be out of range for unsigned, although it will be
converted back into range. What puzzles me more than getting it for unsigned
short is NOT getting it for unsigned int. That doesn't seem consistent. Is
there something special in the standard that would make such an expression,
or the conversion involved in that arithmetic, be different for int compared
to short?

Here's the expression with hard coded types for easier reading (although for
no practical purpose):

((signed short)0) - ((signed short)1) < ((signed short)0)
((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)

((signed int)0) - ((signed int)1) < ((signed int)0)
((unsigned int)0) - ((unsigned int)1) < ((unsigned int)0)

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------

Ben Pfaff 10-26-2009 06:32 PM

Re: warning: comparison is always true due to limited range of data type
 
phil-news-nospam@ipal.net writes:

> ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)


I don't think that this does what you want. Due to the way that
arithmetic promotions work, I think that it ordinarily evaluates
to -1 < 0, which evaluates to 1.

Indeed, on my system:

blp@blp:~(0)$ cat > tmp.c
#include <stdio.h>
int
main(void)
{
printf("%d\n",((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0));
return 0;
}
blp@blp:~(0)$ gcc tmp.c
blp@blp:~(0)$ ./a.out
1
blp@blp:~(0)$
--
Ben Pfaff
http://benpfaff.org

Keith Thompson 10-26-2009 07:18 PM

Re: warning: comparison is always true due to limited range of data type
 
Ben Pfaff <blp@cs.stanford.edu> writes:
> phil-news-nospam@ipal.net writes:
>
>> ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)

>
> I don't think that this does what you want. Due to the way that
> arithmetic promotions work, I think that it ordinarily evaluates
> to -1 < 0, which evaluates to 1.
>
> Indeed, on my system:
>
> blp@blp:~(0)$ cat > tmp.c
> #include <stdio.h>
> int
> main(void)
> {
> printf("%d\n",((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0));
> return 0;
> }
> blp@blp:~(0)$ gcc tmp.c
> blp@blp:~(0)$ ./a.out
> 1
> blp@blp:~(0)$


Here's something that does what you probably want:

#include <stdio.h>
int main(void)
{
if ((unsigned short)-1 < (unsigned short)0) {
puts("unsigned short is a signed type (?!?!?!)");
}
else {
puts("unsigned short is an unsigned type");
}
return 0;
}

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Eric Sosman 10-26-2009 09:18 PM

Re: warning: comparison is always true due to limited range of datatype
 
Keith Thompson wrote:
>
> #include <stdio.h>
> int main(void)
> {
> if ((unsigned short)-1 < (unsigned short)0) {
> puts("unsigned short is a signed type (?!?!?!)");
> }
> else {
> puts("unsigned short is an unsigned type");
> }
> return 0;


Is the second cast necessary? (Have I missed something,
yet again?)

--
Eric Sosman
esosman@ieee-dot-org.invalid

Stefan Ram 10-26-2009 10:32 PM

Re: warning: comparison is always true due to limited range of data type
 
Eric Sosman <esosman@ieee-dot-org.invalid> writes:
>>if ((unsigned short)-1 < (unsigned short)0) {

>Is the second cast necessary? (Have I missed something,
>yet again?)


Without the second cast, the first operand will be
converted (promoted) to »int«, but since it already
has a positive value, the result should be the same.


phil-news-nospam@ipal.net 10-26-2009 10:38 PM

Re: warning: comparison is always true due to limited range of data type
 
On Mon, 26 Oct 2009 11:32:44 -0700 Ben Pfaff <blp@cs.stanford.edu> wrote:

| phil-news-nospam@ipal.net writes:
|
|> ((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0)
|
| I don't think that this does what you want. Due to the way that
| arithmetic promotions work, I think that it ordinarily evaluates
| to -1 < 0, which evaluates to 1.
|
| Indeed, on my system:
|
| blp@blp:~(0)$ cat > tmp.c
| #include <stdio.h>
| int
| main(void)
| {
| printf("%d\n",((unsigned short)0) - ((unsigned short)1) < ((unsigned short)0));
| return 0;
| }
| blp@blp:~(0)$ gcc tmp.c
| blp@blp:~(0)$ ./a.out
| 1
| blp@blp:~(0)$

Oh ... I got caught by that one. The promotion to int happens BEFORE the
minus operation. Ouch.

OK, silly code removed (it was only an optimization hint, anyway).

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------

Peter Nilsson 10-26-2009 11:50 PM

Re: warning: comparison is always true due to limited range of datatype
 
On Oct 27, 9:32*am, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
> Eric Sosman <esos...@ieee-dot-org.invalid> writes:
> > > if ((unsigned short)-1 < (unsigned short)0) {

> >
> > Is the second cast necessary? *(Have I missed something,
> > yet again?)

>
> * Without the second cast, the first operand will be
> * converted (promoted) to »int«, but since it already
> * has a positive value, the result should be the same.


If unsigned short promotes to int, then both sides of <
will be promoted to int. [If you accept that int 'promotes'
to int.] If unsigned short promotes to unsigned int, then
both sides will promote to unsigned int. Both cases are
irrespective of the second cast since int will promote
(via usual arithmetic conversions) to usigned int if the
left operand promotes to unsigned int.

--
Peter


All times are GMT. The time now is 11:12 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.