Before you say this, say two background things you need to know:
(1) The conversion of the type of the language does not modify the original data, it will also open up a temporary or the space specified in the program to store the cast value.
(2) C + + refers to the implementation of the symbol table is moving hands and feet, the corresponding memory address of its own variable symbol is written to the memory address of the variable it refers to.
(3) The execution of the cout function of C + + is to find the corresponding memory address according to the name of the variable, and then fetch the corresponding data from memory according to the type of the variable.
With the above two points of knowledge, see the following program:
#include <iostream>using namespacestd;intMain () {floatA =1.0f; cout<< (int) A <<Endl; cout<< (int&) A <<Endl; cout<<Endl; floatb =0.0f; cout<< (int) b <<Endl; cout<< (int&) b <<Endl; return 0;}
Program execution Results:
First look at (int&) A is what it means:
The meaning of this sentence is to declare an anonymous reference to a, and this reference is temporary, int type. Adds such an entry to the symbol table
(int&) A This expression returns the temporary variable temp, which is a reference, except that the type is int.
So in the execution
cout << (int &) a << Endl;
In this sentence, cout fetches data based on the address and type of temp.
After reading (int&) A, then (int) a? It seems familiar, but really know the specific process. Maybe, look at the following:
As I said earlier, casting the type of data does not modify the contents of the original data. SO (int) A This expression will then produce such an entry in the symbol table:
See, here the temporary variable memory address is not the original address, is the operating system and re-allocated a temporary memory address. The value of this memory address is the value after the variable type is cast.
It can be seen that the two statements are based on the original memory, the float type of data with int output, one is forced to the data type, a new piece of storage space to put the converted value, and then output.
The above analysis is the principle of the program, it should be so realized. But in order to reduce the number of accesses to memory (the symbol table is also in memory Oh ~), the compiler often uses registers to handle these temporary variables, see the assembly Code of the program:
---C:\Program files\microsoft Visual Studio\myprojects\testthread\testthread.cpp--------------------------------- --------------------------------1: #include <iostream>2:using namespacestd;3:4:intMain ()5: {00401780Push EBP00401781mov ebp,esp00401783Sub esp,48h00401786push EBX00401787push ESI00401788Push EDI00401789Lea edi,[ebp-48h]0040178c mov ecx,12h00401791mov eax,0cccccccch00401796Rep stos dword ptr [edi]6:floatA =1.0f;00401798mov DWORD ptr [ebp-4],3f800000h//here, 1.0 is stored in memory as a single-precision floating-point method.7: cout << (int) A <<endl;0040179f push offset @ILT+195(Std::endl) (004010C8) 004017a4 fld dword ptr [EBP-4]//load the data in this memory unit into a floating-point register in floating-point mode004017a7 call __ftol (0042133c)//This function converts the data in the floating-point register into the int type and puts the result in the EAX register. Results after conversion 00000001h004017AC push EAX//data in the output EAX004017AD mov ecx,offset std::cout (0047ff88) 004017b2 call @ILT+245(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004010FA)//ilt is the Entry table for the function in debug mode, the function is called directly under release, and 245 is the output function ordinal of the int type data.004017B7 mov ecx,eax004017b9 call @ILT+470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db)8: cout << (int&) A <<endl;004017be push offset @ILT+195(Std::endl) (004010C8) 004017C3 mov eax,dword ptr [ebp-4]//Copy the value of a directly to the EAX deposit004017C6 push EAX//data in the output EAX004017C7 mov ecx,offset std::cout (0047ff88) 004017CC call @ILT+245(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004010FA) 004017D1 mov ecx,eax004017d3 call @ILT+470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db)9: cout << a <<endl;004017d8 push offset @ILT+195(Std::endl) (004010C8) 004017DD mov ecx,dword ptr [ebp-4]004017e0 push ECX004017E1 mov ecx,offset std::cout (0047ff88) 004017E6 call @ILT+285(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (00401122)//285 is the output function ordinal of the float type data004017EB mov ecx,eax004017ed call @ILT+470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db)Ten: One: cout << Endl <<endl;004017f2 push offset @ILT+195(Std::endl) (004010C8) 004017f7 push offset @ILT+195(Std::endl) (004010C8) 004017FC mov ecx,offset std::cout (0047ff88)00401801Call @ILT +470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db)00401806mov ecx,eax00401808Call @ILT +470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db) A: -:floatb =0.0f; 0040180D mov dword ptr [EBP-8],0 -: cout << (int) b <<Endl;00401814Push offset @ILT +195(Std::endl) (004010C8)00401819FLD DWORD ptr [ebp-8]0040181c call __ftol (0042133c)00401821push EAX00401822mov ecx,offset std::cout (0047ff88)00401827Call @ILT +245(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004010FA) 0040182C mov ecx,eax0040182e call @ILT+470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db) the: cout << (int&) b <<Endl;00401833Push offset @ILT +195(Std::endl) (004010C8)00401838mov Edx,dword ptr [ebp-8]0040183b push edx0040183c mov ecx,offset std::cout (0047ff88)00401841Call @ILT +245(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004010FA)00401846mov ecx,eax00401848Call @ILT +470(std::basic_ostream<Char,std::char_traits<Char>::operator<<) (004011db) -: -:return 0; 0040184D xor Eax,eax -: }
View Code
As seen from assembly language, (int) A is to be cast by type, and the converted value is placed in the register output, (int&) a directly copy the original data into a register output.
Important NOTE:
The symbol table is generated during the compile phase, and the temporary variables, such as temp and TEMP1, are already in the symbol table at compile time, except that the scope is just that sentence. An entry that is not added to the symbol table during the execution phase.
Finally, another point of knowledge: single-precision floating-point numbers, double-precision storage of floating-point numbers.
The storage of single and double precision floating-point numbers is completely different from the way int is stored, and the 1 of int is stored in memory in 00000001h,int 0 is 00000000h, but floating-point numbers are stored in the form of sign bit + order + mantissa.
Take the single-precision float as an example:
It is in the form of 1. M * 2E-127, where E is the index of the shift code form. So for float 1.0, the mantissa m=0, the Order code e=127, the sign bit is 0, so the corresponding machine code is: 3f800000h.
Hint: Why is the floating-point order part to use the shift code?
(1) Use the code to facilitate the operation. 2 of the exponent part has a positive negative, after using the shift code, 2 of the index is still positive negative, but the data of the true storage bit E is completely positive value, without negative values, this can speed up the operation.
(2) In order to unify 0 of floating-point numbers and 0 of integers. The individual bits of the integer 0 are all 0 (recognized), but if you do not need to move the code, the floating-point number of 0 is 1, after the use of the shift code, this is 1.0 * 20-127, because it is too small, then overflow, that is, 0.
Differences in C + + (int&) and (int)