Reputation: 431
In my code, I need to saturate a variable uint32_t var
within a range [MIN, MAX]
.
MIN
and MAX
are defined as macros, so I can change these values easily inside a header file.
Header:
#define MIN (0)
#define MAX (1000)
Code:
if(var > MAX){
var = MAX;
}else if(var < MIN){
var = MIN;
}
When I now use compiler flag -Wtype-limits
, I get a warning that the second check var < MIN
is always false. This warning suggests that I can remove the second comparison.
This makes sense as long as I define #define MIN (0)
but, when changing this to let's say #define MIN (10)
, then the second comparison is mandatory.
So my question: How can I tell the compiler, that MIN
can be any value greater or equal zero?
Upvotes: 5
Views: 449
Reputation: 13189
This solves the issue:
int main(void) {
unsigned int var = rand();
if (var > MAX){
var = MAX;
}
#if MIN > 0
else if (var < MIN) {
var = MIN;
}
#endif
printf("token = %u\n", var);
}
Edit: reduce "dirtiness" by making it clear what the two cases are.
uint32_t saturate(uint32_t var)
{
#if MIN > 0
if (var > MAX){
var = MAX;
}
else if (var < MIN) {
var = MIN;
}
#else
// Only need to do the upper bound
if (var > MAX){
var = MAX;
}
#endif
return var;
}
Upvotes: 3
Reputation: 214265
How can I tell the Compiler, that MIN can be any value greater or equal zero?
You can't, you just told it that it is exactly zero.
This warning comes from the compiler's ability to evaluate integer constant expressions at compile time, so it sees var < 0
and spots that var
is an unsigned type.
We can prevent that and get rid of the warning by using a variable instead, so it's no longer an integer constant expression:
const unsigned int MIN = 0;
Or alternatively, if you must have a macro for some reason, use a compound literal:
#define MIN (const unsigned int){0}
Now of course don't write weird stuff like that without comments, so the correct production code would be for example:
// MIN is using compound literal to block unsigned vs 0 comparison warnings in gcc 1.2.3
#define MIN (const unsigned int){0}
Upvotes: 0
Reputation: 41914
The simplest solution is just use <=
instead of <
if (var >= MAX) {
var = MAX;
} else if (var <= MIN) {
var = MIN;
}
But you should avoid macros if possible and just declare constants instead. Besides always use the U
suffix when you work with unsigned values to avoid signed-unsigned incompatibility warnings. In fact it's quite interesting to see that if I use #define
like that I get a warning in GCC but not Clang, and when I change to const
and add the U
suffix then I get no warning with GCC but one with Clang
Upvotes: 5