问题描述:

Given some code like :

unsigned short val;

//<some unimportant code that sets val>

if(val>65535) val=65535;

How can we disable the "comparison is always false due to limited range of data type" warning from gcc?

This is using GCC 4.1.2, and so doesn't have the #pragma GCC diagnostics construct.

I can't find a -W option to turn it off either.

I have tried doing a cast of val:

if(((long)val)>65535); val=65535

But it seems GCC is clever enough to still give the warning.

The compiler flags are -Wall, and that is it. No -Wextra.

I don't really want to remove the check - short might be 16-bits on this target, but doesn't mean it has to be. I am happy to write the check a different way though.

I want to turn -Werror on, so this warning has to go.

EDIT 1

Unimportant code not so unimportant:

unsigned short val;

float dbValue; (actually function parameter)

val= ((unsigned short) dbValue) & 0xffff);

if(val>65535) val=65535;

So if size of short changes, we will get overflow, and in anycase the range check becomes pointless anyway, and can be deleted, or more to the point applied to the float value instead.

EDIT 2

Whilst the answers so far have helped improve the code, it would still be useful to know if there is any means to disable this warning in gcc 4.1.2 - which is what the question was.

It seems it can be done in recent releases using -Wno-type-limits

网友答案:

In theory there is no answer to your question: if what you intend to write is a no-op (on the particular architecture being targeted) for all possible values of val the code can be reached with, then the compiler can warn that it is a no-op for all…

In practice, comparing (val + 0) instead of val may be enough to let the compiler produce the same code as it did with your original version and at the same time shut up about it.

I would recommend you write

#include <limits.h>
…
#if USHRT_MAX > 65535
if(val>65535) val=65535;
#endif

I feel that if you were to use it without comment, it makes the intention clearer than any convoluted trick.

网友答案:

You could make use of conditional compilation:

#include <limits.h>

unsigned short val;

#if USHRT_MAX > 65535
  if(val>65535) val=65535;
#endif
网友答案:

Using the min macro :

#define min(x, y)   (((x) < (y)) ? (x) : (y))
val=min(val,65535);

gets rid of the warning. So we can also use the same implementation directly

val=(val)<(65535)? val: 65535;

The trick here is that while a 16 bit integer cannot be greater than 65535, it can be 65535, and the check in this version is "is it lower than 65535

网友答案:

val was declared as an unsigned short, which usually (see note) means 16-bit unsigned (0 - 65535), so your test can never be true, because val can never be more than 2^16-1 (65535) with this compiler, and with this target architecture.

Casting it as a long won't change anything. You may want to declare val as unsigned long though.

EDIT

note: as rightly implied in the comments section, the exact width of short and int types depend on both the compiler and the target architecture. Wikipedia has a section on basic C data types that covers the question in greater details.

相关阅读:
Top