How do you format an unsigned long long int using printf? - c

#include <stdio.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Output:
My number is 8 bytes wide and its value is 285212672l. A normal number is 0.
I assume this unexpected result is from printing the unsigned long long int. How do you printf() an unsigned long long int?

Use the ll (el-el) long-long modifier with the u (unsigned) conversion. (Works in windows, GNU).
printf("%llu", 285212672);

%d--> for int
%u--> for unsigned int
%ld--> for long int or long
%lu--> for unsigned long int or long unsigned int or unsigned long
%lld--> for long long int or long long
%llu--> for unsigned long long int or unsigned long long

You may want to try using the inttypes.h library that gives you types such as
int32_t, int64_t, uint64_t etc.
You can then use its macros such as:
#include <inttypes.h>
uint64_t x;
uint32_t y;
printf("x: %"PRIu64", y: %"PRIu32"\n", x, y);
This is "guaranteed" to not give you the same trouble as long, unsigned long long etc, since you don't have to guess how many bits are in each data type.

For long long (or __int64) using MSVS, you should use %I64d:
__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b); //I is capital i

That is because %llu doesn't work properly under Windows and %d can't handle 64 bit integers. I suggest using PRIu64 instead and you'll find it's portable to Linux as well.
Try this instead:
#include <stdio.h>
#include <inttypes.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
/* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Output
My number is 8 bytes wide and its value is 285212672. A normal number is 5.

In Linux it is %llu and in Windows it is %I64u
Although I have found it doesn't work in Windows 2000, there seems to be a bug there!

Compile it as x64 with VS2005:
%llu works well.

How do you format an unsigned long long int using printf?
Since C99 use an "ll" (ell-ell) before the conversion specifiers o,u,x,X.
In addition to base 10 options in many answers, there are base 16 and base 8 options:
Choices include
unsigned long long num = 285212672;
printf("Base 10: %llu\n", num);
num += 0xFFF; // For more interesting hex/octal output.
printf("Base 16: %llX\n", num); // Use uppercase A-F
printf("Base 16: %llx\n", num); // Use lowercase a-f
printf("Base 8: %llo\n", num);
puts("or 0x,0X prefix");
printf("Base 16: %#llX %#llX\n", num, 0ull); // When non-zero, print leading 0X
printf("Base 16: %#llx %#llx\n", num, 0ull); // When non-zero, print leading 0x
printf("Base 16: 0x%llX\n", num); // My hex fave: lower case prefix, with A-F
Output
Base 10: 285212672
Base 16: 11000FFF
Base 16: 11000fff
Base 8: 2100007777
or 0x,0X prefix
Base 16: 0X11000FFF 0
Base 16: 0x11000fff 0
Base 16: 0x11000FFF

Apparently no one has come up with a multi-platform* solution for over a decade since [the] year 2008, so I shall append mine 😛. Plz upvote. (Joking. I don’t care.)
Solution: lltoa()
How to use:
#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));
OP’s example:
#include <stdio.h>
#include <stdlib.h> /* lltoa() */
int main() {
unsigned long long int num = 285212672; // fits in 29 bits
char dummy[255];
int normalInt = 5;
printf("My number is %d bytes wide and its value is %s. "
"A normal number is %d.\n",
sizeof(num), lltoa(num, dummy, 10), normalInt);
return 0;
}
Unlike the %lld print format string, this one works for me under 32-bit GCC on Windows.
*) Well, almost multi-platform. In MSVC, you apparently need _ui64toa() instead of lltoa().

In addition to what people wrote years ago:
you might get this error on gcc/mingw:
main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]
printf("%llu\n", k);
Then your version of mingw does not default to c99. Add this compiler flag: -std=c99.

Non-standard things are always strange :)
for the long long portion
under GNU it's L, ll or q
and under windows I believe it's ll only

One possibility for formatting an unsigned long long is to make use of uintmax_t. This type has been available since C99 and unlike some of the other optional exact-width types found in stdint.h, uintmax_t is required by the Standard (as is its signed counterpart intmax_t).
According to the Standard, a uintmax_t type can represent any value of any unsigned integer type.
You can print a uintmax_t value using the %ju conversion specifier (and intmax_t can be printed using %jd). To print a value which is not already uintmax_t, you must first cast to uintmax_t to avoid undefined behavior:
#include <stdio.h>
#include <stdint.h>
int main(void) {
unsigned long long num = 285212672;
printf("%ju\n", (uintmax_t)num);
return 0;
}

Well, one way is to compile it as x64 with VS2008
This runs as you would expect:
int normalInt = 5;
unsigned long long int num=285212672;
printf(
"My number is %d bytes wide and its value is %ul.
A normal number is %d \n",
sizeof(num),
num,
normalInt);
For 32 bit code, we need to use the correct __int64 format specifier %I64u. So it becomes.
int normalInt = 5;
unsigned __int64 num=285212672;
printf(
"My number is %d bytes wide and its value is %I64u.
A normal number is %d",
sizeof(num),
num, normalInt);
This code works for both 32 and 64 bit VS compiler.

Hex:
printf("64bit: %llp", 0xffffffffffffffff);
Output:
64bit: FFFFFFFFFFFFFFFF

Related

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;
}

How do I sign extend and then find the value of the unsigned binary number in C?

I have a variable declared as an int
int a = -3;
I want the twos' complement values sign extended to 16 bits. So, it becomes: 1111 1111 1111 1101 and then find the unsigned value of this number, which would be 65533 (I believe).
In other words, I want to go from -3 to 65533.
Following this answer: Sign extension from 16 to 32 bits in C I'm stuck on the first step. Here's a shortened version of my code:
#include <stdio.h>
#include <string.h>
int main () {
int s = -3;
printf("%x\n", s);
s = (int16_t)s;
printf("%x\n", s);
int16_t i = s;
printf("%x\n", i);
return(0);
}
I compile with gcc test.c and all three printf statements give "fffffffd"
Do you know why the cast isn't working and perhaps any better solutions to the original problem?
Where you appear to be struggling with the issue is understanding just exactly what bits you are dealing with in interpreting the bits as signed or unsigned or as exact-width types.
How do I sign extend and then find the value of the unsigned binary
number in C?
Answer: you don't -- the bits never change....
When you declare int a = -3;, the bits are set in memory. Thereafter, unless you change them, they are the exact same 32-bits (or whatever sizeof a is on your hardware).
The key to understanding sign-extension is it only applies when interpreting a negative value under a two's complement system when casting or assigning to a larger-size type. Otherwise, you are not extending anything, you are just interpreting the bits as a different type.
A short example for your problem will illustrate. Here int a = -3; is declared (defined) and the bits of a thereafter never change. However, you can interpret those bits (or by lose analogy look at them from a different viewpoint) and use those bits as short, unsigned short, int16_t or uint16_t and in all unsigned cases, interpret them as a hexadecimal value, e.g.
#include <stdio.h>
#include <stdint.h>
#ifdef __GNUC__
#include <inttypes.h>
#endif
int main (void) {
int a = -3;
printf ("a (as int) : %d\n"
"a (as short) : %hd\n"
"a (as unsigned short) : %hu\n"
"a (as unsigned short hex) : 0x%0x\n"
"a (as PRId16) : %" PRId16 "\n"
"a (as PRIu16) : %" PRIu16 "\n"
"a (as PRIx16) : 0x%" PRIx16 "\n",
a, (short)a, (unsigned short)a, (unsigned short)a,
(int16_t)a, (uint16_t)a, (uint16_t)a);
return 0;
}
Example Use/Output
$ ./bin/exact3
a (as int) : -3
a (as short) : -3
a (as unsigned short) : 65533
a (as unsigned short hex) : 0xfffd
a (as PRId16) : -3
a (as PRIu16) : 65533
a (as PRIx16) : 0xfffd
Look things over, and look at all the answers, and let us know if you have any further questions.
Your code causes undefined behaviour by using the wrong format specifier for the argument type in printf.
Here is some correct code:
#include <stdio.h>
int main(void)
{
int s = -3;
uint16_t u = s; // u now has the value 65533
printf("%u\n", (unsigned int)u);
printf("%x\n", (unsigned int)u);
}
The code to printf a uint16_t is slightly complicated, it's simpler to cast to unsigned int and use %u or %x which are specifiers for unsigned int.
fffffffd is the correct two's complement value it's just being printed in hex
use %d in your printf statements
#include <stdio.h>
#include <string.h>
int main () {
int s = -3;
printf("%d\n", s);
s = (int16_t)s;
printf("%d\n", s);
int16_t i = s;
printf("%d\n", i);
return(0);
}
and you should see that 65533 value
In C casting signed value to a wider type automatically extends its sign.
To get a complement value you need to cast your value to appropriate unsigned type:
#include <stdio.h>
#include <stdint.h>
int main ()
{
int s = -3;
printf("%x\n", s);
int16_t s16 = (int16_t)s;
printf("%hd\n", s16);
uint16_t c16 = (uint16_t)s16;
printf("%hu\n", c16);
}
The output I get:
fffffffd
-3
65533

Unexpected unsigned integer behavior

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.

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.

Convert ieee 754 float to hex with c - printf

Ideally the following code would take a float in IEEE 754 representation and convert it into hexadecimal
void convert() //gets the float input from user and turns it into hexadecimal
{
float f;
printf("Enter float: ");
scanf("%f", &f);
printf("hex is %x", f);
}
I'm not too sure what's going wrong. It's converting the number into a hexadecimal number, but a very wrong one.
123.1443 gives 40000000
43.3 gives 60000000
8 gives 0
so it's doing something, I'm just not too sure what.
Help would be appreciated
When you pass a float as an argument to a variadic function (like printf()), it is promoted to a double, which is twice as large as a float (at least on most platforms).
One way to get around this would be to cast the float to an unsigned int when passing it as an argument to printf():
printf("hex is %x", *(unsigned int*)&f);
This is also more correct, since printf() uses the format specifiers to determine how large each argument is.
Technically, this solution violates the strict aliasing rule. You can get around this by copying the bytes of the float into an unsigned int and then passing that to printf():
unsigned int ui;
memcpy(&ui, &f, sizeof (ui));
printf("hex is %x", ui);
Both of these solutions are based on the assumption that sizeof(int) == sizeof(float), which is the case on many 32-bit systems, but isn't necessarily the case.
When supported, use %a to convert floating point to a standard hexadecimal format. Here is the only document I could find that listed the %a option.
Otherwise you must pull the bits of the floating point value into an integer type of known size. If you know, for example, that both float and int are 32 bits, you can do a quick cast:
printf( "%08X" , *(unsigned int*)&aFloat );
If you want to be less dependent on size, you can use a union:
union {
float f;
//char c[16]; // make this large enough for any floating point value
char c[sizeof(float)]; // Edit: changed to this
} u;
u.f = aFloat;
for ( i = 0 ; i < sizeof(float) ; ++i ) printf( "%02X" , u.c[i] & 0x00FF );
The order of the loop would depend on the architecture endianness. This example is big endian.
Either way, the floating point format may not be portable to other architectures. The %a option is intended to be.
HEX to Float
I spend quite a long time trying to figure out how to convert a HEX input from a serial connection formatted as IEE754 float into float. Now I got it. Just wanted to share in case it could help somebody else.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
uint16_t tab_reg[64] //declare input value recieved from serial connection
union IntFloat { int32_t i; float f; }; //Declare combined datatype for HEX to FLOAT conversion
union IntFloat val;
int i;
char buff[50]; //Declare buffer for string
i=0;
//tab_reg[i]=0x508C; //to test the code without a data stream,
//tab_reg[i+1]=0x4369; //you may uncomment these two lines.
printf("Raw1: %X\n",tab_reg[i]); //Print raw input values for debug
printf("Raw2: %X\n",tab_reg[i+1]); //Print raw input values for debug
rs = sprintf(buff,"0X%X%X", tab_reg[i+1], tab_reg[i]); //I need to swap the words, as the response is with the opposite endianness.
printf("HEX: %s",buff); //Show the word-swapped string
val.i = atof(buff); //Convert string to float :-)
printf("\nFloat: %f\n", val.f); //show the value in float
}
Output:
Raw1: 508C
Raw2: 436A
HEX: 0X436A508C
Float: 234.314636
This approach always worked pretty fine to me:
union converter{
float f_val;
unsigned int u_val;
};
union converter a;
a.f_val = 123.1443f;
printf("my hex value %x \n", a.u_val);
Stupidly simple example:
unsigned char* floatToHex(float val){
unsigned char* hexVals = malloc(sizeof(float));
hexVals[0] = ((unsigned char*)&val)[0];
hexVals[1] = ((unsigned char*)&val)[1];
hexVals[2] = ((unsigned char*)&val)[2];
hexVals[3] = ((unsigned char*)&val)[3];
return hexVals;
}
Pretty obvious solution when I figured it out. No bit masking, memcpy, or other tricks necessary.
In the above example, it was for a specific purpose and I knew floats were 32 bits. A better solution if you're unsure of the system:
unsigned char* floatToHex(float val){
unsigned char* hexVals = malloc(sizeof(float));
for(int i = 0; i < sizeof(float); i++){
hexVals[i] = ((unsigned char*)&val)[i];
}
return hexVals;
}
How about this:?
int main(void){
float f = 28834.38282;
char *x = (char *)&f;
printf("%f = ", f);
for(i=0; i<sizeof(float); i++){
printf("%02X ", *x++ & 0x0000FF);
}
printf("\n");
}
https://github.com/aliemresk/ConvertD2H/blob/master/main.c
Convert Hex to Double
Convert Double to Hex
this codes working IEEE 754 floating format.
What finally worked for me (convoluted as it seems):
#include <stdio.h>
int main((int argc, char** argv)
{
float flt = 1234.56789;
FILE *fout;
fout = fopen("outFileName.txt","w");
fprintf(fout, "%08x\n", *((unsigned long *)&flt);
/* or */
printf("%08x\n", *((unsigned long *)&flt);
}

Resources