sudden jump in value when using short int - c

I am trying to run this code where i use short int.
int main() {
short int i=0;
while(++i)
printf("%u\n", i);
}
Ouput (using short int):
1
2
3...
32767
4294934528
.
.
4294967295(last value)
why is there sudden jump in value after 32767 any explanations??
I am using linux(32 bit) os.

Signed integer overflow is undefined behavior. Your program pushes i beyond the bounds of what can be stored in a short, so the program is free to do absolutely anything.

A signed short ranges from -32768 to 32767 and an unsigned short ranges from 0 to 65535. So you are exceeding data size for signed int short.

Related

garbage value while usage of unsigned long int

Program:
#include<stdio.h>
int main()
{
unsigned long int i=1902;
int j=0;
while(j<10)
{
i=i*10;
printf("\n%lu",i);
j++;
}
}
Why am I getting correct results only upto 5 iterations? Please help me to get the correct answer for all iterations. Seeing the range, I changed my int to unsigned long int but still I'm unable to correct the error.
My guess is that you're on a 32-bit system, or using the Microsoft Visual Studio compiler. I guess that because it seems that unsigned long is 32 bits, which means the maximum value it can be is a little over 4 billion.
If you want a 64-bit value then you need to use unsigned long long, which is 64 bits on just about all PC-like systems.
Because at that point the value is out of the range that a unsigned long int can represent, that goes from 0 to 4,294,967,295.
unsigned long int is 4 bytes in almost every C Compiler.
here i is initialized with 1902.
You are multiplying the value of i by 10 at each iteration.
The range of signed long int is from -2,147,483,648 to 2,147,483,647.
By making the variable unsigned you can only double the range of positive integers, ie, from 0 to 4,294,967,295.
The value in variable i crosses maximum range of unsigned integer after 6 iterations. Hence the overflow and negative numbers displayed.
If you want to represent larger numbers use long long int whose size is 64 bits and the range is from −9223372036854775807 to 9223372036854775807.

Signed and Unsigned program error

So today am learning about the signed and unsigned variables. So what i can make out is that signed can have positive, negative and zero values and unsigned can have only the positive values.
So to try this through code i wrote this program in c:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int a=-10;
unsigned int x=-4;
printf("signed variable value is : %d\n Unsigned variable value is : %u",a,x);
}
SO as per my expectation output should be like this :
signed variable value is : -10
Unsigned variable value is : 4
But in reality it turned out to be like this:
signed variable value is : -10
Unsigned variable value is : 4294967292
Can any one explain this !!
When you assign a negative value into a unsigned int and print it using the format specifier %u, 2's complement of that number will be taken into consideration.
So that x become 2's complement of -4, ie 4294967292
A similar question is asked here
Assigning negative numbers to an unsigned int?
The way that unsigned variables work is that they wrap around past 0 (both going forward and back), treating 0 as congruent to 232 (on a 32-bit system). To see this, try the following program:
#include <stdio.h>
int main()
{
unsigned int test = 3;
for (int i = 0; i < 10; ++i)
{
test = test - 1;
printf("%u\n", test);
}
}
Output (on a 32-bit system):
2
1
0
4294967295
4294967294
4294967293
4294967292
4294967291
4294967290
4294967289
Back to your code. -4 is of course the same as 0 - 4 so what you have gotten is the fourth item past 0 on this list.
NB. Your code does not have any errors apart from void main
The unsigned variable doesn't take the absolute value for you.
Since you are putting a negative value in it, it casts the signed integer value (-4) to a 4 byte unsigned variable.
I am guessing the negative values are stored as 2's complement here. Therefore what you get as a -4 on a unsigned 4byte variable is in fact 2^32 -4 (one wrap around) : 4294967292

reverse number for max unsigned int

I try to write a program for reverse the user input number.
The user input range is from 0 < a < 4294967295,
here is EDITED code.
unsigned long int reverseNumber(unsigned long int num)
{
unsigned long int rev = 0;
while (num > 0)
{
rev = rev *10 + (num%10);
num = num/10;
}
return rev;
}
The problem is when I input 4294967295, it will output 1632727628.
Why? I have no idea why it happened.
How can I reverse the 4294967295.
I had changed it to unsigned long int, printf by using %lu, but still output 1632727628. Why?
The reverse of 4294967295 is 5927694924 which is greater than the range of unsigned int
In your system, unsigned int is 32-bit wide, hence the max value that an unsigned int can represent is 4294967295 i.e. 0xFFFFFFFF. That is why your result is overflowing and whatever remains in 32 bits is shown as output.
If you represent 5927694924 in hex, it is 0x16151724C which has extra 33rd bit 1, which is discarded and hence output is 0x6151724C which is 1632727628 in decimal.
To print it on screen you need a greater data type like unsigned long long or uint64_t or unsigned long (on 64-bit systems only), whatever your compiler supports for 64 bit integers.
The reverse of 4294967295 is 5927694924, which is greater than 4294967295, which is the greatest integer which can be stored on 32 bit.
The problem is when I input 4294967295, it will output 1632727628. Why?
unsigned int can store 2^32-1 max. The reverse of 4294967295 is 5927694924 which is much bigger than 2^32-1. Hence the out put is 1632727628. 1632727628 is in fact 5927694924 % 4294967296
To solve this you should have used unsigned long it. But again if the number is great than highest long it'll overflow again.

Initializing unsigned short int to signed value

#include<stdio.h>
int main()
{
unsigned short a=-1;
printf("%d",a);
return 0;
}
This is giving me output 65535. why?
When I increased the value of a in negative side the output is (2^16-1=)65535-a.
I know the range of unsigned short int is 0 to 65535.
But why is rotating in the range 0 to 65535.What is going inside?
#include<stdio.h>
int main()
{
unsigned int a=-1;
printf("%d",a);
return 0;
}
Output is -1.
%d is used for signed decimal integer than why here it is not following the rule of printing the largest value of its(int) range.
Why the output in this part is -1?
I know %u is used for printing unsigned decimal integer.
Why the behavioral is undefined in second code and not in first.?
This I have compiled in gcc compiler. It's a C code
On my machine sizeof short int is 2 bytes and size of int is 4 bytes.
In your implementation, short is 16 bits and int is 32 bits.
unsigned short a=-1;
printf("%d",a);
First, -1 is converted to unsigned short. This results in the value 65535. For the precise definition see the standard "integer conversions". To summarize: the value is taken modulo USHORT_MAX+1.
This value 65535 is assigned to a.
Then for the printf, which uses varargs, the value is promoted back to int. varargs never pass integer types smaller than int, they're always converted to int. This results in the value 65535, which is printed.
unsigned int a=-1;
printf("%d",a);
First line, same as before but modulo UINT_MAX+1. a is 4294967295.
For the printf, a is passed as an unsigned int. Since %d requires an int the behavior is undefined by the C standard. But your implementation appears to have reinterpreted the unsigned value 4294967295, which has all bits set, as as a signed integer with all-bits-set, i.e. the two's-complement value -1. This behavior is common but not guaranteed.
Variable assignment is done to the amount of memory of the type of the variable (e.g., short is 2 bytes, int is 4 bytes, in 32 bit hardware, typically). Sign of the variable is not important in the assignment. What matters here is how you are going to access it. When you assign to a 'short' (signed/unsigned) you assign the value to a '2 bytes' memory. Now if you are going to use '%d' in printf, printf will consider it 'integer' (4 bytes in your hardware) and the two MSBs will be 0 and hence you got [0|0](two MSBs) [-1] (two LSBs). Due to the new MSBs (introduced by %d in printf, migration) your sign bit is hidden in the LSBs and hence printf considers it unsigned (due to the MSBs being 0) and you see the positive value. To get a negative in this you need to use '%hd' in first case. In the second case you assigned to '4 bytes' memory and the MSB got its SIGN bit '1' (means negative) during assignment and hence you see the negative number in '%d' of printf. Hope it explains. For more clarification please comment on the answer.
NB: I used 'MSB' for a shorthand of higher-order byte(s). Please read it according to the context (e.g., 'SIGN bit' will make you read like 'Most Significant Bit'). Thanks.

Overflow in C code

Can anyone explain to me why this code prints "error" ? This only appears for minimal value of integer.
int abs(int x) {
int result = 0;
if(x < 0)
result = -1*x;
else
result = x;
return result;
}
int main() {
printf("Testing abs... ");
if (abs(-2147483648) != 2147483648)
printf("error\n");
else
printf("success\n");
}
Because for a 32 bit integer signed integer, using two's complement, the largest number you can store is 2147483647.
The range is -2147483648 2147483647.
You must be careful - overflowing signed numbers is undefined behavior.
The maximal value of a 32 bit integer is 2,147,483,647.
put long instead of int. For bigger integers you will need long long. Google for the range that this types offer. Also for the comparison with a static number you must declare it like e.g. 8438328L
Because of the way integers are represented (2's complement), if your int is 32 bits, -2147483648 is its own negative.
After -2147483648 is returned by your abs(), it is probably being compared as a long, 64-bit integer. If the comparison were 32-bit, 2147483648 would be equivalent to -2147483648. Perhaps if you turn on all warnings for your compiler, it will complain?
The range of 32-bit signed integers is, as has been mentioned before -2147483648 (= -231) to 2147483647 (= 231 - 1). In your abs() function, you have thus overflow of a signed integer, which is undefined behaviour (citation of standard to be inserted). Therefore anything could happen, but what actually happens is very probably that the result just wraps around, producing -2147483648 again. However, you compare that to the integer literal 2147483648, which does not fit into a 32-bit signed integer, hence, since it has no (n)signedness suffix, that literal has the next type in the list
int
long int
long long int
which can represent its value (if any). On 64-bit systems that could be long int or long long int, the former is typically the case on Linux, the latter, as far as I know on Windows, on 32-bit systems it's almost certainly long long int.
Then the int value -2147483648 is promoted to long (long) int and the tested condition is
if (-2147483648L != 2147483648L) // or LL

Resources