This question already has answers here:
How do I detect unsigned integer overflow?
(31 answers)
Closed 7 years ago.
I have two unsigned 32 bit integers, call them x and y. I want to periodically increment the two uint32's by seemingly random uint32 values. x and y will accumulate and I want them to continue to accumulate until they hit their limit, at which point I want them to start back at 0 + the value they would have had added had they not overflowed.
Assume the code looks like:
//This would be called, say every 5 seconds
void increment_vals(uint32_t *x, uint32_t *y, uint32_t x_inc, uint32_t y_inc)
{
*x += x_inc;
*y += y_inc;
if (x overflowed || y overflowed)
{
*x = x_inc;
*y = y_inc;
}
}
So basically my question is: how do I know when x OR y has overflowed and need to to be reset? Should I just store x and y before incrementing and if the result is less than the original value then it must have overflowed? Is that guaranteed?
Thanks.
You could check for overflow before incrementing:
if(x_inc > (MAXINT - *x)) {
//about to overflow
}
I suggest
uint32_t xx = *x + x_inc;
if (xx < *x)
*x = 0;
else *x = xx;
I found this document quite helpful and descriptive in answering my question, particularly page 172:
"For unsigned integers, if the sum is smaller than either operand,
an overflow has occurred."
Related
This question already has answers here:
Unsigned values in C
(3 answers)
Closed 9 months ago.
I ran into an interesting scenario with integer conversion:
#include <stdio.h>
int main()
{
unsigned int x = 20;
unsigned int y = 40;
printf("%d\n", x - y);
printf("%d\n", (x - y) / 4);
}
~ % ./a.out
-20
1073741819
I wasn't expecting the 2nd result. Since x and y are both unsigned ints is the result of x - y unsigned (and in this case displayed as signed by printf)?
The things you are printing are indeed unsigned integers and you should print them with %u, but that does not explain the surprising result for the second number. The surprising result comes from an overflow occurring when you calculate x - y, since the result of that subtraction is negative and thus not representable as an unsigned int.
Unsigned overflow/underflow is not undefined behavior, so it's OK to have code like this in production if you know what you are doing.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I want to convert float negative values to unsigned int values. Is it possible?
For example:
float x = -10000.0;
int y;
y = x;
When we assign x value to y, can the negative value be stored in an integer?
If not, how can we store the negative values into integer variables?
can the negative (float f) value be stored in an integer?
Yes, with limitations.
With a signed integer type like int16_t i, i = f is well defined for
-32768.999... to 32767.999...
With an unsigned integer type like unt16_t u, u = f is well defined for
-0.999... to 65535.999...
The result is a truncated value (fraction thrown away). All other float values result in undefined behavior.
If not, how can we store the negative values into integer variables?
Best to use wide signed integer types and test for range limitations.
In any case, the fraction of the float is lost. A -0.5f can be stored in an unsigned, yet the value becomes 0u.
The below performs some simply tests to insure y is in range.
#include <limits.h>
float x = ...;
int y = 0;
if (x >= INT_MAX + 1u) puts("Too pos");
else if (x <= INT_MIN - 1.0) puts("Too neg");
else y = (int) x;
Note the tests above are illustrative as they lack high portability.
Example: INT_MIN - 1.0 in inexact in select situations.
To cope, with common 2's complement int, the below is better reformed. As 2's complement, INT_MIN is a power of 2 (negated) and usually in the range of float, thus making for an exact subtraction near the negative threshold. `
// if (x <= INT_MIN - 1.0)
if (x - INT_MIN <= - 1.0f)
Another alternative is to explore a union. Leave that for others to explain its possibilities and limitations.
union {
float f;
unsigned u;
} x;
float x = 10000.0;
int a;
a = (int)(x+0.5);
This question already has answers here:
How do I detect unsigned integer overflow?
(31 answers)
Closed 6 years ago.
I'm having a problem with my little c program.
I'm trying to print out a warning if an overflow occurs, I'm using the limits.h library to recognise an overflow with INT_MAX.
I guess the problem is in my if loop, but I can't really find the problem...
#include<stdio.h>
#include<limits.h>
int main()
{
int x = 1627964;
int y = 9;
for(int i=1; i<y; ++i){
x*= i; // x= x * i
printf("%d * %d \n",x , i+1);
if(x >= INT_MAX){
printf("An Overflow has occured!\n");
return 0;
break;
}
}
}
I think the overflow occurs after multiplying with 7:
1627964 * 2
3255928 * 3
9767784 * 4
39071136 * 5
195355680 * 6
1172134080 * 7
-384996032 * 8
1214999040 * 9
I can't really tell why the warning is not printed out...
Some help would be really appreciated, thanks :)
Only unsigned int has defined overflow behavior, signed int does not, so compiler could throw away half of your code if it detect it. Anyway in your code int never will be bigger than INT_MAX because on overflow it should be negative value.
If you try int max / i < x for the overflow ?
x == INT_MAX only tests if x is exactly equal to INT_MAX. Not less, not more, exactly equal.
What you should be testing for is signed integer overflow, which happens when you multiply by 1627964 by 8: if (x==INT_MAX || x < 0) - the sign bit gets incremented which makes your value negative.
This question already has answers here:
John Carmack's Unusual Fast Inverse Square Root (Quake III)
(6 answers)
Closed 8 years ago.
I found a very complex function this is an implementation of Fast inverse square root. I honestly do not understand how this function works but the following conversion between a long and a float has caught my eye:
i = *(long *) &y;
And I leave the full code
inline float Q_rsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = *(long *) &y;
i = 0x5f3759df - (i >> 1);
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y));
return y;
}
The cast simply reinterprets the bits of y as a long so that it can perform integer arithmetic on them.
See Wikipedia for an explanation of the algorithm: Fast inverse square root.
The code makes use of the knowledge that, on the target platform, sizeof(long) == sizeof(float).
#R.. also helpfully adds the following in a comment:
It's also invalid C -- it's an aliasing violation. A correct version of this program needs use either memcpy or possibly (this is less clear that it's correct, but real compilers document support for it) union-based type punning. The version in OP's code will definitely be "miscompiled" (i.e. in a way different than the author's intent) by real compilers though.
This means that the code is not only architecture-specific, it is also compiler-specific.
This question already has answers here:
Detecting signed overflow in C/C++
(13 answers)
Closed 8 years ago.
I'm working with signed 16 bit wide variables.
When adding, subtracting etc, can i detect the carry and overflow the following way:
I store the result in a 32bit wide variable, and then check the 17th bit (bits from 0-16 represent the value, and if there's carry or overflow the 17h bit should be 1 - overflow)?
If it's one then it's an overflow/carry, if it's zero - it isn't.
Can carry happen without overflow, or vice versa, when working with 16b values?
I searched StackOverflow, but i was unable to find a clear answer to my question.
upd:
One can use approach, when operands are testing against the limits (declared in the limits.h) when doing the operation. E.g. look at this "safe" addition function:
int safe_add(int x, int y)
{
if(y < 0)
return save_sub(x, -y);
if(x > (INT_MAX - y))
{
printf("overflow\n");
return INT_MAX;
}
return x + y;
}
int save_sub(int x, int y)
{
if(y < 0)
return save_add(x, -y);
if(x > (INT_MIN + y))
{
printf("underflow\n");
return INT_MIN;
}
return x - y;
}
Note: these methods have at least one bug: they may fail if invoked on the largest negative integer, INT_MIN.