在C语言中的各种赋值是如何转换的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C语言中的各种赋值是如何转换的?相关的知识,希望对你有一定的参考价值。

关于赋值操作,你可以查看一下博客的内容,初学者不用理解底层汇编的实现机制,有点晦涩,随着自己的进步可以进一步的深入底层查看其实现原理

1 代码案例
iint main()


int n,m;
char ch;
float f = 12.12;
double d=121.111;
n = f; //单精度浮点赋值给整数
m =d; //双精度浮点赋值给整数
ch = n; //整数赋值给字符值
ch = f; //浮点赋值给字符值
f = d; //整数变量赋值给浮点变量;
return 0;

2 以上代码调试运行对应的汇编代码分析
101: float f = 12.12; //单精度浮点赋值:占用4个字节,需要1条汇编指令实现
源代码对应1条汇编指令:
00401C78 mov dword ptr [ebp-10h],4141EB85h

102: double d=121.111; //双精度浮点赋值:占用8个字节,需要2条汇编指令实现
源代码对应2条汇编指令:
00401C7F mov dword ptr [ebp-18h],9FBE76C9h
00401C86 mov dword ptr [ebp-14h],405E471Ah

103: n = f; //单精度浮点赋值给整数
源代码对应3条汇编指令:
00401C8D fld dword ptr [ebp-10h]
00401C90 call __ftol (004232cc)
00401C95 mov dword ptr [ebp-4],eax

104: m =d; //双精度浮点赋值给整数
源代码对应3条汇编指令:实际的类型转换通过调用内部C运行时接口函数__ftol来实现类型转换。
00401C98 fld qword ptr [ebp-18h]
00401C9B call __ftol (004232cc) //调用__ftol函数(对应15条汇编指令,见下面3描述)
00401CA0 mov dword ptr [ebp-8],eax

105: ch = n; //整数赋值给字符值
源代码对应2条汇编指令:
00401CA3 mov al,byte ptr [ebp-4]
00401CA6 mov byte ptr [ebp-0Ch],al

106: ch = f; //浮点赋值给字符值
源代码对应3条汇编指令:
00401CA9 fld dword ptr [ebp-10h]
00401CAC call __ftol (004232cc)
00401CB1 mov byte ptr [ebp-0Ch],al

107: f = d; // 整数转换为浮点数,源代码对应2条汇编指令:
00401CB4 fld qword ptr [ebp-18h]
00401CB7 fstp dword ptr [ebp-10h]

3 赋值涉及的__ftol函数对应的汇编指令:
__ftol 函数对应以下16条指令:
004232CC push ebp
004232CD mov ebp,esp
004232CF add esp,0F4h
004232D2 wait
004232D3 fnstcw word ptr [ebp-2]
004232D6 wait
004232D7 mov ax,word ptr [ebp-2]
004232DB or ah,0Ch
004232DE mov word ptr [ebp-4],ax
004232E2 fldcw word ptr [ebp-4]
004232E5 fistp qword ptr [ebp-0Ch]
004232E8 fldcw word ptr [ebp-2]
004232EB mov eax,dword ptr [ebp-0Ch]
004232EE mov edx,dword ptr [ebp-8]
004232F1 leave
004232F2 ret

4 C运行库(Run-Time Library)存在的原因
4.1 定义(摘自《软件调试》,张银奎)
当编译器在将高级语言编译到第几语言的过程是,因为高级语言中的某些比较负责的运算符(如不同的类型转换)要对应比较多的低级语言指令(如汇编、机器指 令),为了防止这样的指令段多次重复出现在目标代码中(造成目标码过大),编译器通常将这些指令段封装为函数,然后将高级语言的某些操作翻译为函数调用。
C标准定义了标准C函数,C++标准定义了C++标准类库,这些库通常被称为支持库,这些库是程序编译运行的必要条件,因此支持库也称为运行库(Run-Time Library).
VC提供了C和C++运行库。
4.2 例子
1)如上面例子,VC编译器通常将 n =f( n :整数,f:浮点数)这样的赋值编译为调用__ftol函数;
2)VC编译器也将new ,delete 操作符编译为对malloc和free函数调用(可以通过单步调试运行,反汇编单步跟着call 指令观察分析验证!)

5 总结
1)通过以上分析,不同类型变量转换,是编译程序在编译程序过程中,将操作转换编译成调用运行库函数来实现的。
2)一般程序设计过程中,不是必要情况下,不要频繁使用不同类型互相转换的操作,特别是涉及到循环运算、性能的优化的程序!

参考资料:http://blog.sina.com.cn/s/blog_6fd68d5f0100n60w.html

参考技术A c中有很多“隐式的”转换,也就是使用者看不到、由系统完成的。很多,几乎无处不在。比如:int a;a=-1;
此时是将-1这个const signed int 类型数转换成signed int 。诸如此类的类型转换几乎很少被注意到,而我们更关注“显式的”类型转换。比如:
t=(int)sqrt(num);
for (int i=2;i<=t;i++) if (num%i==0) return false;return true;
这个判断素数的程序段使用了强制类型转换,将sqrt的double型结果强制转换成int型。另外,sqrt函数的参数也是double型的!所以在处理函数参数时,系统进行了隐式的转换。

c中还有一些“奇怪的”赋值。比如char型与整型可以直接运算,原理是使用了ASCII码。而非零的整形可以认为是布尔型true,零则可以看成false。
参考技术B 有很多转换的函数,书籍都有介绍

C语言中的数据类型转换


变量的数据类型是可以转换的。转换的方法有两种,一种是自动转换,一种是强制转换。
1) 自动转换:在不同类型数据的混合运算中,由系统自动实现转换,由少字节类型向多字节类型转换。不同类型的量相互赋值时也由系统自动进行转换,把赋值号右边的类型转换为左边的类型。
2) 强制转换:由强制转换运算符完成转换

1 自动转换

自动转换发生在不同数据类型的变量混合运算时,由编译系统自动完成。类型自动转换的规则如下:

1)若参与运算量的类型不同,则先转换成同一类型,然后进行运算;
2) 转换按数据长度增加的方向进行,以保证精度不降低。如 int 型和 long 型运算时,先把 int 量转成 long
型后再进行运算。
3) 所有的浮点运算都是以双精度进行的,即使仅含 float 单精度量运算的表达式,也要先转换成 double
型,再作运算。
4) char 型和 short 型参与运算时,必须先转换成 int 型。
5) 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。

2 强制类型转换

强制类型转换是通过类型转换运算来实现的。
其一般形式为:(类型说明符) (表达式)
其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。
在使用强制转换时应注意以下问题:
1) 类型说明符和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y 则成了把 x转换成 int 型之后再与 y 相加了。
2) 无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。

以上是关于在C语言中的各种赋值是如何转换的?的主要内容,如果未能解决你的问题,请参考以下文章

c语言中将一个浮点型赋值给整型时,会不会四舍五入?

C语言中,如何将一个数组中的数值转换成字符串输出?

C语言中,如何将一个数组中的数值转换成字符串输出?

C语言,自动类型转换怎么做?

C语言中的赋值语句

C语言中的数据类型转换