4

For example,

float f = 2.4;
int n = f + 1;

n = 3

variable f is 0x4019999a in memory, So I thought f + 1 = 0x4019999a + 1 but Computer doesn't. How to know f is 'float'? Even if f is just 0x4019999a in memory. Is the type of variable stored somewhere?

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 2
    Once the compiler is finished, the types are effectively lost. They can be deduced by examining the assembly instructions generated by the compiler, but the types themselves aren't stored anywhere. – Some programmer dude Aug 19 '21 at 07:14
  • While the compiler is doing its thing, it keeps information about the types of identifiers in an internal table (that does not necessarily get outputted to the produced binary). With `gcc` you can try adding [debugging options](https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html) to the generation of the binary. – pmg Aug 19 '21 at 07:18
  • 2
    Everything in the computer is a number. What is means is from its *context*. At processor level, many arithmetic instructions do not know whether a number is signed or unsigned, but the programmer uses different *flags* that it sets. In your example, the compiler generates the appropriate instructions, so the data type is inherent in that. – Weather Vane Aug 19 '21 at 07:18
  • duplicates: [How and where in memory does the compiler store the information about what type a variable is?](https://stackoverflow.com/q/20279568/995714), [Variable types in C and who keeps track of it](https://stackoverflow.com/q/47960007/995714), [how data types are processed by Compiler](https://stackoverflow.com/q/14640562/995714), [where the info about type is stored and how type safety check is performed?](https://stackoverflow.com/q/32130520/995714) – phuclv Aug 19 '21 at 09:53
  • Does this answer your question? [how data types are processed by Compiler](https://stackoverflow.com/questions/14640562/how-data-types-are-processed-by-compiler) – phuclv Aug 19 '21 at 09:53
  • I actually wanted to create on a TypeInfo Engine that would take preprocessed output and create a file that contains the type info, but if you want something more simple for your projects you can simply use macros for defining your variables like: `#define define(type, name) const char* name ## Type = #type; type name` and use it like this: `define(int, foo) = 5; printf("%s foo = %d", fooType, foo);` – WENDYN Aug 20 '21 at 22:14

3 Answers3

5

The type isn't stored explicitly (in an optimized production executable; debugging outputs have all sorts of extra information in them).

"So if the type isn't stored, how does it know how to handle f = f + 1 differently from n = n + 1?" I hear you ask. :-) The answer is that the compiler knew the type when it was compiling, and it output different CPU instructions for those operations. In the f case, it output instructions that work with floating point values, but in the n case, it output instructions that work with two's complement integers.

WedaPashi
  • 3,561
  • 26
  • 42
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Types of variables are not stored. The compiler emits the machine code instructions accordingly to the code you write.

In your example:

float f = 2.4;
int n = f + 1;

float value 2.4 is being converted to int and its value is 2. 1 is added to the integer value 2. The result is 3. The physical representation of f in memory does not matter.

If you want to add 1 to the physical memory representation of the f treated as an unsigned integer you need to:

float f = 2.4f;
unsigned n,m;

memcpy(&n, &f, sizeof(n));
m = n + 1;
0___________
  • 60,014
  • 4
  • 34
  • 74
0

Type only matters during translation, when the compiler is analyzing your source code and generating the equivalent machine code. That's when rules like "the operand of unary * must have pointer type" and "operands of + must have arithmetic type" and "the type and number of parameters in a function call must match the function declaration" and so forth are enforced.

Type information is not explicitly stored in the generated machine code. Depending on the types used in the source code, the generated machine code will use different opcodes and registers based on the size of an object and whether or not it's floating point. On x86 for example, when adding two single precision floats together, the compiler will add the instruction addss to the machine code; when adding two 32-bit ints together, it will add the instruction addl.

So I thought f + 1 = 0x4019999a + 1 but Computer doesn't.

An int cannot store fractional values - the rule in C is that when you assign a floating-point value to an integer target, the fractional portion is truncated. n cannot store 3.4, it can only store 3.

I took your snippet above and wrapped it in a complete program, compiled it1, then looked at the generated machine code. The lines

float f = 2.4;
int n = f + 1;

translate to the following:

movss   LCPI0_0(%rip), %xmm0    ## xmm0 = mem[0],zero,zero,zero
movss   LCPI0_1(%rip), %xmm1    ## xmm1 = mem[0],zero,zero,zero
...
movss   %xmm1, -8(%rbp)
addss   -8(%rbp), %xmm0
cvttss2si   %xmm0, %eax
movl    %eax, -12(%rbp)

The movss instruction copies single-precision float values from one location to another - in this case, it's copying the floating point values 2.4 and 1.0 to the floating point registers %xmm0 and %xmm1, respectively. The value in %xmm1 (2.4) is copied to the location -8(%rpb), which is the space for the variable f. That value is added to the value in %xmm0 (1.0). At this point %xmm0 contains the value 3.4. That value is then converted to its integer equivalent (3) by the cvttss2si instruction and the result is stored in 32-bit general purpose (i.e., non-floating point) register %eax. That result is then copied to n (-12(%rbp)).

Remember that floating-point values and integer values have completely different representations. The binary representation of the 32-bit integer value 1 is 0x00000001; the binary representation of the single-precision floating point value 1.0 is 0x3f800000.


  1. Apple LLVM version 10.0.1 (clang-1001.0.46.4)
    Target: x86_64-apple-darwin18.6.0
John Bode
  • 119,563
  • 19
  • 122
  • 198