Using %f to print an integer variable - c

The output of the following c program is: 0.000000
Is there a logic behind the output or is the answer compiler dependent or I am just getting a garbage value?
#include<stdio.h>
int main()
{
int x=10;
printf("%f", x);
return 0;
}
PS:- I know that to try to print an integer value using %f is stupid. I am just asking this from a theoretical point of view.

From the latest C11 draft — §7.16 Variable arguments <stdarg.h>:
§7.16.1.1/2
...if type is not compatible with the type of the actual next argument
(as promoted according to the default argument promotions), the behavior
is undefined, except for the following cases:
— one type is a signed integer type, the other type is the corresponding
unsigned integer type, and the value is representable in both types;
— one type is pointer to void and the other is a pointer to a character type.

The most important thing to remember is that, as chris points out, the behavior is undefined. If this were in a real program, the only sensible thing to do would be to fix the code.
On the other hand, looking at the behavior of code whose behavior is not defined by the language standard can be instructive (as long as you're careful not to generalize the behavior too much).
printf's "%f" format expects an argument of type double, and prints it in decimal form with no exponent. Very small values will be printed as 0.000000.
When you do this:
int x=10;
printf("%f", x);
we can explain the visible behavior given a few assumptions about the platform you're on:
int is 4 bytes
double is 8 bytes
int and double arguments are passed to printf using the same mechanism, probably on the stack
So the call will (plausibly) push the int value 10 onto the stack as a 4-byte quantity, and printf will grab 8 bytes of data off the stack and treat it as the representation of a double. 4 bytes will be the representation of 10 (in hex, 0x0000000a); the other 4 bytes will be garbage, quite likely zero. The garbage could be either the high-order or low-order 4 bytes of the 8-byte quantity. (Or anything else; remember that the behavior is undefined.)
Here's a demo program I just threw together. Rather than abusing printf, it copies the representation of an int object into a double object using memcpy().
#include <stdio.h>
#include <string.h>
void print_hex(char *name, void *addr, size_t size) {
unsigned char *buf = addr;
printf("%s = ", name);
for (int i = 0; i < size; i ++) {
printf("%02x", buf[i]);
}
putchar('\n');
}
int main(void) {
int i = 10;
double x = 0.0;
print_hex("i (set to 10)", &i, sizeof i);
print_hex("x (set to 0.0)", &x, sizeof x);
memcpy(&x, &i, sizeof (int));
print_hex("x (copied from i)", &x, sizeof x);
printf("x (%%f format) = %f\n", x);
printf("x (%%g format) = %g\n", x);
return 0;
}
The output on my x86 system is:
i (set to 10) = 0a000000
x (set to 0.0) = 0000000000000000
x (copied from i) = 0a00000000000000
x (%f format) = 0.000000
x (%g format) = 4.94066e-323
As you can see, the value of the double is very small (you can consult a reference on the IEEE floating-point format for the details), close enough to zero that "%f" prints it as 0.000000.
Let me emphasize once again that the behavior is undefined, which means specifically that the language standard "imposes no requirements" on the program's behavior. Variations in byte order, in floating-point representation, and in argument-passing conventions can dramatically change the results. Even compiler optimization can affect it; compilers are permitted to assume that a program's behavior is well defined, and to perform transformations based on that assumption.
So please feel free to ignore everything I've written here (other than the first and last paragraphs).

Because an integer 10 in binary looks like this:
00000000 00000000 00000000 00001010
All printf does is take the in-memory representation and try to present it as an IEEE 754 floating point number.
There are three parts to a floating point number (from MSB to LSB):
The sign: 1 bit
The exponent: 8 bits
The mantissa: 23 bits
Since an integer 10 is just 1010 in the mantissa bits, its a very tiny number that is much less than the default precision of printf's floating point format.

The result is not defined.
I am just asking this from a theoretical point of view.
The complete chris's excellent answer:
What happens in your printf is undefined, but it could be quite similar to the code below (it depends on the actual implementation of the varargs, IIRC).
Disclaimer: The following is more "as-if-it-worked-that-way" explanation of what could happen in an undefined behaviour case on one platform than a true/valid description that always happens on all platforms.
Define "undefined" ?
Imagine the following code:
int main()
{
int i = 10 ;
void * pi = &i ;
double * pf = (double *) pi ; /* oranges are apples ! */
double f = *pf ;
/* what is the value inside f ? */
return 0;
}
Here, as your pointer to double (i.e. pf) points to an address hosting an integer value (i.e. i), what you'll get is undefined, and most probably garbage.
I want to see what's inside that memory !
If you really want to see what's possibly behind that garbage (when debugging on some platforms), try the following code where we will use an union to simulate a piece of memory where we will write either double or int data:
typedef union
{
char c[8] ; /* char is expected to be 1-byte wide */
double f ; /* double is expected to be 8-bytes wide */
int i ; /* int is expected to be 4-byte wide */
} MyUnion ;
The f and i field are used to set the value, and the c field is used to look at (or modify) the memory, byte by byte.
void printMyUnion(MyUnion * p)
{
printf("[%i %i %i %i %i %i %i %i]\n"
, p->c[0], p->c[1], p->c[2], p->c[3], p->c[4], p->c[5], p->c[6], p->c[7]) ;
}
the function above will print the memory layout, byte by byte.
The function below will prinf the memory layout of different types of values:
int main()
{
/* this will zero all the fields in the union */
memset(myUnion.c, 0, 8 * sizeof(char)) ;
printMyUnion(&myUnion) ; /* this should print only zeroes */
/* eg. [0 0 0 0 0 0 0 0] */
memset(myUnion.c, 0, 8 * sizeof(char)) ;
myUnion.i = 10 ;
printMyUnion(&myUnion) ; /* the representation of the int 10 in the union */
/* eg. [10 0 0 0 0 0 0 0] */
memset(myUnion.c, 0, 8 * sizeof(char)) ;
myUnion.f = 10 ;
printMyUnion(&myUnion) ; /* the representation of the double 10 in the union */
/* eg. [0 0 0 0 0 0 36 64] */
memset(myUnion.c, 0, 8 * sizeof(char)) ;
myUnion.f = 3.1415 ;
printMyUnion(&myUnion) ; /* the representation of the double 3.1415 in the union */
/* eg. [111 18 -125 -64 -54 33 9 64] */
return 0 ;
}
Note: This code was tested on Visual C++ 2010.
It doesn't mean it will work that way (or at all) on your platform, but usually, you should get results similar to what happens above.
In the end, the garbage is just the hexadecimal data set in the memory your looking at, but seen as some type.
As most types have different memory representation of the data, looking at the data in any other type than the original type is bound to have garbage (or not-so-garbage) results.
Your printf could well behave like that, and thus, try to interpret a raw piece of memory as a double when it was initially set as an int.
P.S.: Note that as the int and the double have different size in bytes, the garbage gets even more complicated, but it is mostly what I described above.
But I want to print an int as a double!
Seriously?
Helios proposed a solution.
int main()
{
int x=10;
printf("%f",(double)(x));
return 0;
}
Let's look at the pseudo code to see what's being fed to the printf:
/* printf("...", [[10 0 0 0]]) ; */
printf("%i",x);
/* printf("...", [[10 0 0 0 ?? ?? ?? ??]]) ; */
printf("%f",x);
/* printf("...", [[0 0 0 0 0 0 36 64]]) ; */
printf("%f",(double)(x));
The casts offers a different memory layout, effectively changing the integer "10" data into a double "10.0" data.
Thus, when using "%i", it will expect something like [[?? ?? ?? ??]], and for the first printf, receive [[10 0 0 0]] and interpret it correctly as an integer.
When using "%f", it will expect something like [[?? ?? ?? ?? ?? ?? ?? ??]], and receive on the second printf something like [[10 0 0 0]], missing 4 bytes. So the 4 last bytes will be random data (probably the bytes "after" the [[10 0 0 0]], that is, something like [[10 0 0 0 ?? ?? ?? ??]]
In the last printf, the cast changed the type, and thus the memory representation into [[0 0 0 0 0 0 36 64]] and the printf will interpret it correctly as a double.

essentially it's garbage. Small integers look like unnormalized floating point numbers which shouldn't exist.

You could cast the int variable like this:
int i = 3;
printf("%f",(float)(i));

Related

Why does a high-value input prevent an array from using the actual input value in C?

I'm making a function that takes a value using scanf_s and converts that into a binary value. The function works perfectly... until I put in a really high value.
I'm also doing this on VS 2019 in x64 in C
And in case it matters, I'm using
main(int argc, char* argv[])
for the main function.
Since I'm not sure what on earth is happening, here's the whole code I guess.
BinaryGet()
{
// Declaring lots of stuff
int x, y, z, d, b, c;
int counter = 0;
int doubler = 1;
int getb;
int binarray[2000] = { 0 };
// I only have to change things to 1 now, am't I smart?
int binappend[2000] = { 0 };
// Get number
printf("Gimme a number\n");
scanf_s("%d", &getb);
// Because why not
printf("\n");
// Get the amount of binary places to be used (how many times getb divides by 2)
x = getb;
while (x > 1)
{
d = x;
counter += 1;
// Tried x /= 2, gave me infinity loop ;(
x = d / 2;
}
// Fill the array with binary values (i.e. 1, 2, 4, 8, 16, 32, etc)
for (b = 1; b <= counter; b++)
{
binarray[b] = doubler * 2;
doubler *= 2;
}
// Compare the value of getb to binary values, subtract and repeat until getb = 0)
c = getb;
for (y = counter; c >= 1; y--)
{
// Printing c at each subtraction
printf("\n%d\n", c);
// If the value of c (a temp variable) compares right to the binary value, subtract that binary value
// and put a 1 in that spot in binappend, the 1 and 0 list
if (c >= binarray[y])
{
c -= binarray[y];
binappend[y] += 1;
}
// Prevents buffer under? runs
if (y <= 0)
{
break;
}
}
// Print the result
for (z = 0; z <= counter; z++)
{
printf("%d", binappend[z]);
}
}
The problem is that when I put in the value 999999999999999999 (18 digits) it just prints 0 once and ends the function. The value of the digits doesn't matter though, 18 ones will have the same result.
However, when I put in 17 digits, it gives me this:
99999999999999999
// This is the input value after each subtraction
1569325055
495583231
495583231
227147775
92930047
25821183
25821183
9043967
655359
655359
655359
655359
131071
131071
131071
65535
32767
16383
8191
4095
2047
1023
511
255
127
63
31
15
7
3
1
// This is the binary
1111111111111111100100011011101
The binary value it gives me is 31 digits. I thought that it was weird that at 32, a convenient number, it gimps out, so I put in the value of the 32nd binary place minus 1 (2,147,483,647) and it worked. But adding 1 to that gives me 0.
Changing the type of array (unsigned int and long) didn't change this. Neither did changing the value in the brackets of the arrays. I tried searching to see if it's a limit of scanf_s, but found nothing.
I know for sure (I think) it's not the arrays, but probably something dumb I'm doing with the function. Can anyone help please? I'll give you a long-distance high five.
The problem is indeed related to the power-of-two size of the number you've noticed, but it's in this call:
scanf_s("%d", &getb);
The %d argument means it is reading into a signed integer, which on your platform is probably 32 bits, and since it's signed it means it can go up to 2³¹-1 in the positive direction.
The conversion specifiers used by scanf() and related functions can accept larger sizes of data types though. For example %ld will accept a long int, and %lld will accept a long long int. Check the data type sizes for your platform, because a long int and an int might actually be the same size (32 bits) eg. on Windows.
So if you use %lld instead, you should be able to read larger numbers, up to the range of a long long int, but make sure you change the target (getb) to match! Also if you're not interested in negative numbers, let the type system help you out and use an unsigned type: %llu for an unsigned long long.
Some details:
If scanf or its friends fail, the value in getb is indeterminate ie. uninitialised, and reading from it is undefined behaviour (UB). UB is an extremely common source of bugs in C, and you want to avoid it. Make sure your code only reads from getb if scanf tells you it worked.
In fact, in general it is not possible to avoid UB with scanf unless you're in complete control of the input (eg. you wrote it out previously with some other, bug free, software). While you can check the return value of scanf and related functions (it will return the number of fields it converts), its behaviour is undefined if, say, a field is too large to fit into the data type you have for it.
There's a lot more detail on scanf etc. here.
To avoid problems with not knowing what size an int is, or if a long int is different on this platform or that, there is also the header stdint.h which defines integer types of a specific width eg. int64_t. These also have macros for use with scanf() like SCNd64. These are available from C99 onwards, but note that Windows' support of C99 in its compilers is incomplete and may not include this.
Don't be so hard on yourself, you're not dumb, C is a hard language to master and doesn't follow modern idioms that have developed since it was first designed.

Why does multiplying uint8_t with an integer result in a 0?

I tried to code a program, but i'm having problems with 1 small segment.
for(uint8_t i = 1; i < MAX_BIT_VALUE; i*=2){
printf("Current value of i: %u\n", i);
}
When I run this segment, I get this output:
Current value of i: 0
Current value of i: 0
Current value of i: 0
Current value of i: 0
in an infinite loop. I don't understand why. uint8_t is an unsigned integer of 8-bits. I merely multiplied i which has value 1 by 2. How could it possibly become 0?
If i changed the data type of i to int however, it works just fine:
Current value of i: 1
Current value of i: 2
Current value of i: 4
Current value of i: 8
Current value of i: 16
...
I tried to find a possible answer online, but I don't know how to phrase the problem to get an answer. Could you guys help me please?
Apart from what the other answer recommend on the printing, you have the following problem:
multipy i==128 by 2
result 256
storing it 256 (0x100) in an unsigned 8bit results in 0,
because 8 bit are to narrow
multiply 0 by 2
result 0
0 < 255 -> endless loop
Your code causes undefined behavior.
The flag value # is not supposed to be used with u conversion specifier.
Quoting C11,chapter §7.21.6.1
# The result is converted to an ‘‘alternative form’’. For o conversion, it increases
the precision, if and only if necessary, to force the first digit of the result to be a
zero (if the value and precision are both 0, a single 0 is printed). For x (or X)
conversion, a nonzero result has 0x (or 0X) prefixed to it. For a, A, e, E, f, F, g,
and G conversions, the result of converting a floating-point number always
contains a decimal-point character, even if no digits follow it. (Normally, a
decimal-point character appears in the result of these conversions only if a digit
follows it.) For g and G conversions, trailing zeros are not removed from the
result. For other conversions, the behavior is undefined.
For fixed width integers use the format specifier MACROS as defined in inttypes.h, like PRIu8 for a 8-bit unsigned integer type.
After you fix this the next problem is, overflow of the 8-bit variable. As described in the other answer by Yunnosch Once i becomes 128, you multiple it by 2, and store the result back in the 8-bit variable, the result is 0. Then,
0 multiplied by anything remains 0
which constitutes a forever TRUE condition in the for loop, i < MAX_BIT_VALUE part.
and you get the infinite loop.
Change the printf format string from:
printf("Current value of i: %#u\n", i);
to
printf("Current value of i: %"PRIu8"\n", i);
and it should be fine. The PRIu8 macro is defined in inttypes.h

how to tell the value of a float pointer when it has been referenced from an integer? ex: float *f= (float *)someInteger

I cannot figure out how to convert the value of a referenced float pointer when it is referenced from an integer casted into a float pointer. I'm sorry if I'm wording this incorrectly. Here is an example of what I mean:
#include <stdio.h>
main() {
int i;
float *f;
i = 1092616192;
f = (float *)&i;
printf("i is %d and f is %f\n", i, *f);
}
the output for f is 10. How did I get that result?
Normally, the value of 1092616192 in hexadecimal is 0x41200000.
In floating-point, that will give you:
sign = positive (0b)
exponent = 130, 2^3 (10000010b)
significand = 2097152, 1.25 (01000000000000000000000b)
2^3*1.25
= 8 *1.25
= 10
To explain the exponent part uses an offset encoding, so you have to subtract 127 from it to get the real value. 130 - 127 = 3. And since this is a binary encoding, we use 2 as the base. 2 ^ 3 = 8.
To explain the significand part, you start with an invisible 'whole' value of 1. the uppermost (leftmost) bit is half of that, 0.5. The next bit is half of 0.5, 0.25. Because only the 0.25 bit and the default '1' bit is set, the significand represents 1 + 0.25 = 1.25.
What you are trying to do is called type-punning. It should be done via a union, or using memcpy() and is only meaningful on an architecture where sizeof(int) == sizeof(float) without padding bits. The result is highly dependent on the architecture: byte ordering and floating point representation will affect the reinterpreted value. The presence of padding bits would invoke undefined behavior as the representation of float 15.0 could be a trap value for type int.
Here is how you get the number corresponding to 15.0:
#include <stdio.h>
int main(void) {
union {
float f;
int i;
unsigned int u;
} u;
u.f = 15;
printf("re-interpreting the bits of float %.1f as int gives %d (%#x in hex)\n",
u.f, u.i, u.u);
return 0;
}
output on an Intel PC:
re-interpreting the bits of float 15.0 as int gives 1097859072 (0x41700000 in hex)
You are trying to predict the consequence of an undefined activity - it depends on a lot of random things, and on the hardware and OS you are using.
Basically, what you are doing is throwing a glass against the wall and getting a certain shard. Now you are asking how to get a differently formed shard. well, you need to throw the glass differently against the wall...

Why does printing an uninitialized bool array as integers produce values besides 0 and 1? [duplicate]

This question already has answers here:
Mystery with bool data type
(3 answers)
Closed 7 years ago.
(Also see Mystery with bool data type for a similar question with relevant answers.)
While debugging a program, I noticed strange output when printing an uninitialized bool array as integers. Consider this C program:
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n = 30;
bool* bools = malloc(n * sizeof(bool)); // Uninitialized memory.
for (int i=0; i<n; ++i)
{
int x = bools[i];
assert(x == 0 || x == 1);
printf("%d ", x);
}
printf("\n");
free(bools);
}
Due to the uninitialized bool array, the output varies with each run based on previous memory contents, of course. My understanding is that casting a bool to an int should always produce either 0 or 1 (see the assertion above, which always passes); however, I frequently see output like this:
0 0 0 0 0 0 0 144 0 0 0 0 0 0 0 144 16 0 92 113 255 127 0 0 160 41 222 134 255 127
Can someone explain how this program can print anything besides 0s and 1s?
Update: The short answer is that casting an uninitialized bool to int can produce values besides 0 and 1. (In my case, bools are stored as bytes, so their uninitialized values can be anything in [0..255].) Also, the assert line above seems to be optimized out, which made this problem more difficult to debug.
To provide a little more context: I was originally writing a function to count the number of set bits in a bool array, e.g.:
int popcount(const bool* v, int n)
{
int c=0;
for (int i=0; i<n; ++i) c += v[i];
return c;
}
I noticed that sometimes this would return a result greater than n, which seemed impossible. The problem was that the bool array was uninitialized. Zeroing the array fixed the problem, but it still doesn't make sense to me how casting a bool to an int could produce something besides 0 or 1.
Because it doesn't make sense to restrict boolean read operations to clamp the actual value to either 0 or 1.
The value of an undefined variable can be anything that fits within the variable's size. A bool usually occupies a single byte (because that's the smallest addressable unit), and on systems with 8-bit bytes it means a bool can store 256 different values. That's why the numbers you're seeing range from 0 to 255.
The implementation is free to assume that you will not invoke UB, that's why you're seeing values besides 0 and 1. In code without UB, all bools would convert to either 0 or 1.
A bool (_Bool) object can only hold values 0 or 1. In your case your program invokes undefined behavior as you are accessing uninitialized memory returned by malloc which has indeterminate value.
A strictly conforming program will only evaluate _Bool objects to 0 or 1.

What's the first double that deviates from its corresponding long by delta?

I want to know the first double from 0d upwards that deviates by the long of the "same value" by some delta, say 1e-8. I'm failing here though. I'm trying to do this in C although I usually use managed languages, just in case. Please help.
#include <stdio.h>
#include <limits.h>
#define DELTA 1e-8
int main() {
double d = 0; // checked, the literal is fine
long i;
for (i = 0L; i < LONG_MAX; i++) {
d=i; // gcc does the cast right, i checked
if (d-i > DELTA || d-i < -DELTA) {
printf("%f", d);
break;
}
}
}
I'm guessing that the issue is that d-i casts i to double and therefore d==i and then the difference is always 0. How else can I detect this properly -- I'd prefer fun C casting over comparing strings, which would take forever.
ANSWER: is exactly as we expected. 2^53+1 = 9007199254740993 is the first point of difference according to standard C/UNIX/POSIX tools. Thanks much to pax for his program. And I guess mathematics wins again.
Doubles in IEE754 have a precision of 52 bits which means they can store numbers accurately up to (at least) 251.
If your longs are 32-bit, they will only have the (positive) range 0 to 231 so there is no 32-bit long that cannot be represented exactly as a double. For a 64-bit long, it will be (roughly) 252 so I'd be starting around there, not at zero.
You can use the following program to detect where the failures start to occur. An earlier version I had relied on the fact that the last digit in a number that continuously doubles follows the sequence {2,4,8,6}. However, I opted eventually to use a known trusted tool (bc) for checking the whole number, not just the last digit.
Keep in mind that this may be affected by the actions of sprintf() rather than the real accuracy of doubles (I don't think so personally since it had no troubles with certain numbers up to 2143).
This is the program:
#include <stdio.h>
#include <string.h>
int main() {
FILE *fin;
double d = 1.0; // 2^n-1 to avoid exact powers of 2.
int i = 1;
char ds[1000];
char tst[1000];
// Loop forever, rely on break to finish.
while (1) {
// Get C version of the double.
sprintf (ds, "%.0f", d);
// Get bc version of the double.
sprintf (tst, "echo '2^%d - 1' | bc >tmpfile", i);
system(tst);
fin = fopen ("tmpfile", "r");
fgets (tst, sizeof (tst), fin);
fclose (fin);
tst[strlen (tst) - 1] = '\0';
// Check them.
if (strcmp (ds, tst) != 0) {
printf( "2^%d - 1 <-- bc failure\n", i);
printf( " got [%s]\n", ds);
printf( " expected [%s]\n", tst);
break;
}
// Output for status then move to next.
printf( "2^%d - 1 = %s\n", i, ds);
d = (d + 1) * 2 - 1; // Again, 2^n - 1.
i++;
}
}
This keeps going until:
2^51 - 1 = 2251799813685247
2^52 - 1 = 4503599627370495
2^53 - 1 = 9007199254740991
2^54 - 1 <-- bc failure
got [18014398509481984]
expected [18014398509481983]
which is about where I expected it to fail.
As an aside, I originally used numbers of the form 2n but that got me up to:
2^136 = 87112285931760246646623899502532662132736
2^137 = 174224571863520493293247799005065324265472
2^138 = 348449143727040986586495598010130648530944
2^139 = 696898287454081973172991196020261297061888
2^140 = 1393796574908163946345982392040522594123776
2^141 = 2787593149816327892691964784081045188247552
2^142 = 5575186299632655785383929568162090376495104
2^143 <-- bc failure
got [11150372599265311570767859136324180752990210]
expected [11150372599265311570767859136324180752990208]
with the size of a double being 8 bytes (checked with sizeof). It turned out these numbers were of the binary form "1000..." which can be represented for far longer with doubles. That's when I switched to using 2n-1 to get a better bit pattern: all one bits.
The first long to be 'wrong' when cast to a double will not be off by 1e-8, it will be off by 1. As long as the double can fit the long in its significand, it will represent it accurately.
I forget exactly how many bits a double has for precision vs offset, but that would tell you the max size it could represent. The first long to be wrong should have the binary form 10000..., so you can find it much quicker by starting at 1 and left-shifting.
Wikipedia says 52 bits in the significand, not counting the implicit starting 1. That should mean the first long to be cast to a different value is 2^53.
Although I'm hesitant to mention Fortran 95 and successors in this discussion, I'll mention that Fortran since the 1990 standard has offered a SPACING intrinsic function which tells you what the difference between representable REALs are about a given REAL. You could do a binary search on this, stopping when SPACING(X) > DELTA. For compilers that use the same floating point model as the one you are interested in (likely to be the IEEE754 standard), you should get the same results.
Off hand, I thought that doubles could represent all integers (within their bounds) exactly.
If that is not the case, then you're going to want to cast both i and d to something with MORE precision than either of them. Perhaps a long double will work.

Resources