Unexpected unsigned integer behavior - c

I encountered this unexpected output with the following code in which I was verifying the maximum values (represented in decimal form) of the unsigned forms of short and int types when all their bits were set to 1.
#include <stdio.h>
int main()
{
unsigned int n1 = 0xFFFFFFFF;
unsigned short n2 = 0xFFFF;
printf("\nMax int = %+d", n1);
printf("\nMax short = %+d", n2);
return 0;
}
The output I get is (compiled using the Visual Studio 2017 C/C++ Compiler):
Max int = -1
Max short = +65535
Along the lines of unsigned short, I was expecting the maximum value of the unsigned int to be +4294967295. Why isn't it so?

You need to use %u for the format specifier for an unsigned type.

Using printf(), your conversions in the format string must match the type of the arguments, otherwise the behavior is undefined. %d is for int.
Try this for the maximum values:
#include <stdio.h>
int main()
{
printf("Max unsigned int = %u\n", (unsigned)-1);
printf("Max unsigned short = %hu\n", (unsigned short)-1);
return 0;
}
Side notes:
the maximum value of any unsigned type is -1 cast to that type.
Put newline at the end of your lines. Among other reasons, this flushes stdouts buffer with the default setting of line buffered.

Related

why itoa fuction returns 32 bits if the size of variable in 16 bit

size of short int is 2 bytes(16 bits) on my 64 bit processor and mingw compiler but when I convert short int variable to a binary string using itoa function
it returns string of 32 bits
#include<stdio.h>
int main(){
char buffer [50];
short int a=-2;
itoa(a,buffer,2); //converting a to binnary
printf("%s %d",buffer,sizeof(a));
}
Output
11111111111111111111111111111110 2
The answer is in understanding C's promotion of short datatypes (and char's, too!) to int's when those values are used as parameters passed to a function and understanding the consequences of sign extension.
This may be more understandable with a very simple example:
#include <stdio.h>
int main() {
printf( "%08X %08X\n", (unsigned)(-2), (unsigned short)(-2));
// Both are cast to 'unsigned' to avoid UB
return 0;
}
/* Prints:
FFFFFFFE 0000FFFE
*/
Both parameters to printf() were, as usual, promoted to 32 bit int's. The left hand value is -2 (decimal) in 32bit notation. By using the cast to specify the other parameter should not be subjected to sign extension, the printed value shows that it was treated as a 32 bit representation of the original 16 bit short.
itoa() is not available in my compiler for testing, but this should give the expected results
itoa( (unsigned short)a, buffer, 2 );
your problem is so simple , refer to itoa() manual , you will notice its prototype which is
char * itoa(int n, char * buffer, int radix);
so it takes an int that to be converted and you are passing a short int so it's converted from 2 byte width to 4 byte width , that's why it's printing a 32 bits.
to solve this problem :
you can simply shift left the array by 16 position by the following simple for loop :
for (int i = 0; i < 17; ++i) {
buffer[i] = buffer[i+16];
}
and it shall give the same result , here is edited version of your code:
#include<stdio.h>
#include <stdlib.h>
int main(){
char buffer [50];
short int a= -2;
itoa(a,buffer,2);
for (int i = 0; i < 17; ++i) {
buffer[i] = buffer[i+16];
}
printf("%s %d",buffer,sizeof(a));
}
and this is the output:
1111111111111110 2

C - How to print calculated numbers that have 15 digits?

I tried to print the result of 99,999 * 99,999 * 99,999, the result should have been 999,970,000,299,999 but what got printed instead was 18446744072244127711. I tried to print 20000 * 20000 * 20000 and the result was pretty much the same. Can you guys tell me how to get the real result?
#include <stdio.h>
int main()
{
int num;
printf("Insert number : ");
scanf("%ld", &num);
fflush(stdin);
unsigned long long int total = num * num * num;
printf("Result : %llu", total);
getchar();
return 0;
}
One way to do it is:
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main(void)
{
uint64_t x = 99999;
printf("%" PRIu64 "\n", x*x*x);
}
You may also be able to do this with unsigned long or unsigned long long types, but these depend on your C implementation (the compiler you are using).
The arithmetic you attempted overflowed the supported range of the int type you were using. When programming, it is important to ensure that the calculations you do will not overflow the range of the types you use.
Additionally, you must be careful about types in C code:
When using scanf, match the conversion specifier to the type. For example, when scanning a decimal numeral for an int object, you should use %d, not %ld. %ld is for long int.
In unsigned long long int total = num*num*num;, the unsigned long long int affects the type of total. It does not affect the type used in the calculation num*num*num. In that expression, the type of num is used. To use unsigned long long int in the calculation, you would have to convert one or all of the operands to unsigned long long int, as by using a cast: (unsigned long long int) num * num * num.
By assigning 99999 to a uint64_t object, which I named x, I ensured that x*x*x was calculated with uint64_t arithmetic. (uint64_t is a 64-bit unsigned integer.) Another way to do this would be with UINT64_C(99999) * UINT64_C(99999) * UINT64_C(99999). UINT64_C is a macro defined in stdint.h that essentially means “treat this constant as having type uint64_t or wider (actually uint_least64_t).” This could also be done with UINT64_C(99999) * 99999 * 99999 because C will automatically convert the narrower-type integer operands to the wider-type integer operand. It could also be done with (uint64_t) 99999 * 99999 * 99999.
PRIu64 is a macro that provides the right printf conversion specifier for uint64_t. It is defined in inttypes.h.
Bugs:
%ld on an int invokes undefined behavior.
fflush(stdin) invokes undefined behavior since stdin is an input stream.
num*num*num is carried out on operands that have type int, so you get overflow if you attempt 99999 * 99999 * 99999 since this is a larger number than 231-1 (assuming 32 bit int).
Fixed code:
#include <stdio.h>
int main(void)
{
int num;
printf("Insert number : ");
scanf("%d",&num); getchar();
long long int total = (long long)num*num*num;
printf("Result : %llu",total);
getchar();
return 0;
}

C - unsigned int going negative (-ve)

What I know is - UNSIGNED INT cannot take negative values.
If I take the maximum value of an UNSIGNED INT and increment it, I should get ZERO i.e. the minimum value and if I take the minimum value and decrement it, I should get the maximum value.
Then, why is this happening ?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main()
{
unsigned int ui;
ui = UINT_MAX;
ui ++;
printf("ui = %d", ui);
ui = 0;
ui --;
printf("\n");
printf("ui = %d", ui);
return EXIT_SUCCESS;
}
Output:
ui = 0
ui = -1
From 'man 3 printf':
d, i The int argument is converted to signed decimal notation
So, although the type of ui is unsigned int, printf is interpreting it as a signed int and showing it as such.
That is because you using %d format specifier that says printf to treat your number as a signed integer.
Try using %u to output unsigned value and you get the desired result.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main()
{
unsigned int ui;
ui = UINT_MAX;
ui ++;
printf("ui = %u", ui);
ui = 0;
ui --;
printf("\n");
printf("ui = %u", ui);
return EXIT_SUCCESS;
}
output:
ui = 0
ui = 4294967295
Check out the reference on possible format specifiers.
printf("%u") should be used for unsigned ints.
You pass the value to an ellipsis function (printf). You should expect nothing about the signedness here.
The %d in the format string controls the sign of the displayed value. There is a cast inside the printf function since you selected the %d. That's why you see a signed value that is equivalent to the binary value FFFFFFFF1.
1 Assuming a 32 bit width for integer.

long long multiplication in C gives wrong result

My C code seems to be malfunctioning and incapable of multiplying long long numbers and outputting the result, and I can't for the life of me figure out why.
Here's the culprit code:
#include "stdio.h"
int main()
{
unsigned long long primes[] = {199453LL, 200723LL, 203317LL, 205103LL, 206603LL, 208057LL, 210323LL, 210961LL, 212827LL, 214237LL, 215693LL, 216319LL};
unsigned long long numbers[6];
int i;
printf("Calculating the numbers to factor!\n");
printf("Size of long: %i\n", sizeof(long));
printf("Size of long long: %i\n", sizeof(long long));
for (i = 0; i < 6; i++)
{
numbers[i] = primes[i]*primes[11-i];
printf("%ld*%ld = %ld\n", primes[i], primes[11-i], numbers[i]);
printf("Result is %ld\n",numbers[i]);
}
return 0;
}
And here's the output when I compile this and run it (I'm using gcc version 4.8.2 on Linux)
Calculating the numbers to factor!
Size of long: 4
Size of long long: 8
199453*0 = 216319
Result is 195800547
200723*0 = 215693
Result is 344873079
203317*0 = 214237
Result is 608351169
205103*0 = 212827
Result is 701783221
206603*0 = 210961
Result is 635502523
208057*0 = 210323
Result is 809499451
Your printf format string is wrong. %ld requires a long int, %lld is for a long long int, and since you are using unsigned long long, you should use %llu, otherwise large positive values will be displayed as negative.
And, as noticed by Grzegorz Szpetkowski, the size_t (sizeof) requires %zu.
From printf(3):
l (ell) A following integer conversion corresponds to a long int or unsigned long int argument, or a following n conversion
corresponds to a pointer to a long int argument, or a following c conversion corresponds to a wint_t argument, or a following s conversion corresponds to a pointer to wchar_t argument.
ll (ell-ell). A following integer conversion corresponds to a long long int or unsigned long long int argument, or a following
n conversion corresponds to a pointer to a
long long int argument.
...
z A following integer conversion corresponds to a size_t or ssize_t argument. (Linux libc5 has Z with this meaning. Don't use it.)
Now, for example this output
199453*0 = 216319
Occurs because the little-endian 64-bit numbers 199453, 216319 and 43145473507 are correctly pushed onto the stack; but printf expects to find only 32-bit numbers on the stack, so it prints 199453, 0 (which are the top 4 bytes of 64-bit number 199453), and 216319.

Function Returning Value of Type I don't Want it to Return

For a problem at school, I need to convert a ASCII string of character digits to a decimal value. I wrote a function to do this and specified the return type to be an unsigned short as you can see in the code below.
#include <stdio.h>
unsigned short str_2_dec(char* input_string, int numel);
int main()
{
short input;
char input_string[6]= "65535";
input = str_2_dec(input_string, 5);
printf("Final Value: %d", input);
return 0;
}
unsigned short str_2_dec(char* input_string, int numel)
{
int factor = 1;
unsigned short value = 0;
int index;
for(index=0; index <(numel-1); index++)
{
factor *= 10;
}
for(index = numel; index > 0; index--)
{
printf("Digit: %d; Factor: %d; ", *(input_string+(numel-index))-48, factor);
value += factor * ((*(input_string+(numel - index))-48));
printf("value: %d\n\n", value);
factor /= 10;
}
return value;
}
When running this code, the program prints -1 as the final value instead of 65535. It seems it's displaying the corresponding signed value anyway. Seems like something very simple, but I can't find an answer. A response would be greatly appreciated.
The return type for str_2_dec() is unsigned short but you are storing the value in a (signed) short variable. You should declare your variables the appropriate type otherwise you will have problems as you have observed.
In this case, you converted "65535" to an unsigned short which has the bit pattern FFFFHex. That bit pattern was reinterpreted as a (signed) short which is the decimal value -1.
You should change your main() to something like this:
int main()
{
unsigned short input; /* to match the type the function is returning */
char input_string[6]= "65535";
input = str_2_dec(input_string, 5);
printf("Final Value: %hf", input);
return 0;
}
The problem is that you are taking the unsigned short return value of the function and storing it in a (signed) short variable, input. Since the value is outside the range representable in short, and since short is signed, this results in either an implementation-defined result or an implementation-defined signal being raised.
Change the type of input to unsigned short and everything will be fine.
You mean that is printing index as it was a (signed) short here?
short input;
...
printf("Final Value: %d", input);
Update: Since the hint doesn't seem to be catching, I will be more direct: Your declaration of input should be unsigned short input;.
You are using the wrong format specifier in printf. try using %u instead of %d
The problem isn't with the function but with how you are printing the return value.
printf("Final Value: %d", input);
The %d is place-holder for int type, not short.
Use %hu instead.
You didn't use the correct format specifier for the
short input;
printf("final value=%d\n",input);
This makes the difference of your out put.

Resources