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.
Related
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:
Strange behaviour of the pow function
(5 answers)
Closed 7 years ago.
I was simply writing a program to calculate the power of an integer. But the output was not as expected. It worked for all the integer numbers except for the power of 5.
My code is:
#include <stdio.h>
#include <math.h>
int main(void)
{
int a,b;
printf("Enter the number.");
scanf("\n%d",&a);
b=pow(a,2);
printf("\n%d",b);
}
The output is something like this:
"Enter the number. 2
4
"Enter the number. 5
24
"Enter the number. 4
16
"Enter the number. 10
99
Can't we use pow() function for int data type??
Floating point precision is doing its job here. The actual working of pow is using log
pow(a, 2) ==> exp(log(a) * 2)
Look at math.h library which says:
###<math.h>
/* Excess precision when using a 64-bit mantissa for FPU math ops can
cause unexpected results with some of the MSVCRT math functions. For
example, unless the function return value is stored (truncating to
53-bit mantissa), calls to pow with both x and y as integral values
sometimes produce a non-integral result. ... */
Just add 0.5 to the return value of pow and then convert it to int.
b = (int)(pow(a,2) + 0.5);
So, the answer to your question
Does pow() work for int data type in C?
Not always. For integer exponentiation you could implement your own function (this will work for 0 and +ve exp only):
unsigned uint_pow(unsigned base, unsigned exp)
{
unsigned result = 1;
while (exp)
{
if (exp % 2)
result *= base;
exp /= 2;
base *= base;
}
return result;
}
there is no int based pow. What you are suffering from is floating point truncation.
an int based pow is too constrained (the range of inputs would quickly overflow an int). In many cases int based pow, like in your case where its powers of 2 can be done efficiently other ways.
printf("%a", pow(10, 2)) and see what you get; I expect you'll see you don't quite get 100. Call lround if you want to round instead of truncating.
The C library function double pow(double x, double y)
It takes double type
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."
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
signed to unsigned conversions
A riddle (in C)
I am trying to understand why this program is not working
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
I came across this program when I was going through automatic type conversions in C.But I don't understand how conversions happen between signed and unsigned data types.Please explain.
Thank you,
Harish
sizeof() is of type unsigned, wile d is signed.
you check if d is smaller then an unsigned integer. Thus, the signed d is converted to unsinged.
But the bits representaion of the signed -1 when read as unsigned is greater then 2^31, and obviously greater then TOTAL_ELEMENTS-2, thus the condition is never met and you do not enter the for loop even once.
Look at this code snap, it might clear up things for you:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int x = 50;
int y = -1;
printf("x < y is actually %u < %u which yields %u\n", y,x,y < x);
return 0;
}
The above code prints:
x < y is actually 4294967295 < 50 which yields 0