`
ChuanSu
  • 浏览: 52746 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

C/C++, 类型转换 发生了什么?

阅读更多
C语言中,数据类型间的转换,主要体现在内存间的转换,或者可以说体现在 bit 的转换,数据类型在内存的中都是以 bit 的形式体现的。
C/C++
  • char   1 byte
  • short  2 bytes
  • int    4 bytes
  • long   4 bytes
  • float  4 bytes
  • double 8 bytes

来看几个简单的例子,就会明白数据类型在转换的时候究竟发生了什么。
char ch ='A';
short s = ch;
printf("%d",s);

在console中的结果是 65。

在内存中 variable ch 是这样存储的
                65               

在内存中,数据类型都是以二进制的形式存储的,所以当看到一个十进制的数字的时候,应该时刻想着强大的数字 2
65 = 64 +1 = 2^6+2^0
char ch 占1个byte
01000001

short s = ch; 这行代码发生了什么?首先我们知道short是占2个bytes
           
所以  char ch
01000001
short s             
0000000001000001

从上面表格可以看出 在将char ch赋值给 short s 时 只是将char ch的 8个bit copy到 short s 的低8位,而short s多余的8-bit 空间,就 just padded(填补)在这里由0填补.

再来看个例子,
int i = pow(2,23)+pow(2,21)+pow(2,14)+7;//2^23+2^21+2^14+7
short s = i;
printf("%d",s);

结果一定是 short s = 2^14+7.

上面之所以写成2的指数的形式,是为了方便书写2进制,来看下 int i 的存储形式
00000000101000000100000000000111

short s
0100000000000111

int 型 在内存中占32 bit 但是short 型只有16 bit的空间来储存,那么以16 bit的空间去存储32 bit 的 pattern, 显然不可以,所以在C/C++ 中,就简单的将int型的低位16位 copy到 short的16位 内存空间。至于高位16位没有发生移动。这个又叫做 bit pattern copy。
所有short s = 2^14+7。

再来看个简单的例子。
short s = -1;
int i = s;
printf("%d",i);

variable short s的存储形式 为
1111111111111111

注意,最高位的 1, 仅仅为一个 符号,sign,只起到标记+/-的作用。在http://chuansu.iteye.com/blog/1435150有详细的介绍,在这不多讲了。

当 evaluate int i = s;时, int i 的内存又是如何的?
11111111111111111111111111111111


在讲到第一个例子的时候,我们提到过,对于short 多余的8 bit的空间 用0填充了。
这里,因为int型 有32-bit的足够大的储存空间,所有根据bit pattern copy,就可以简单的将上面short s =-1的 16-bit copy到 int型的 32-bit储存空间,而不丢失信息。
如果和第一个例子一样,将剩余的16-bit都用0填充,那么对于int i的最高位,也就是标记位,为0,表示正数,这就不相符了。所以在C/C++中,就简单的将 short s最高位的sign 1 扩展到其余的16-bit. 这个就称作 sign extention。

最后看一道我们学校的 考试题
引用
What is the output of the following program (1P)
# include <stdio.h>

int main(void){

	unsigned char uc1 = 0x256;
	unsigned char uc2 = 12;
	printf("%d %d | %x %x\n",
			uc1,uc2,uc1,uc2);
	
	return 0;
}

16进制与2进制的相互转化一定要熟悉掌握
0x256
现转化2 -> 0010;
     5 -> 0101;
     6 -> 0110;
所以0x256 的 二进制形式为 0010 0101 0110。
由上面说到的 bit pattern copy 可以知道
unsigned char uc1 = 0x256. 只能将低8位 copy 到 char uc1的8位存储空间中。
所有 char uc1
01010110

然后转化为 10进制 就为 2^1+2^2+2^4+2^6 = 86; %d(10进制) uc1 = 86;
%x,是指 去掉0x的16进制数, uc1 = 86; 由10进制转化为16进制,以2进制为桥梁,
86 的二进制为0101 0110
然后每四个bit一组 分别转化16进制 0101 -> 2^0+2^2 = 5;
                             0110 -> 2^1+2^2 = 6;
所以86的16进制为 56。 %x uc1 = 56;

同理可得出 %d uc2 = 12; %x uc2 = C。

本文主要介绍了 在C/C++ 类型转化时发生了什么? int short char间的转化。
那么float double与 int或者 short 发生转化时又是怎样的?以及float double在内存中又是怎么存储的?

未完-待续。


分享到:
评论

相关推荐

    C_C++问题总结

    3.12 两种常用的实现隐式类类型转换的方式是什么?如何避免隐式类 型转换?3.13 STL中的vector:增减元素对迭代器的影响 3.14 STL中排序算法的实现 3.15 C和C++的区别 3.16 内存对齐 3.17 C++转换机制(static_cast...

    经典C/C++面试题目大汇总(全附答案).doc

    因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。 引用型参数应该在能被定义为const的情况下,尽量定义为const 。 5. 将“引用”作为函数返回值类型的格式、好处和需要遵守的...

    C和C++头文件对比一览

    C、传统 C++ #include &lt;assert.h&gt; //设定插入点 #include &lt;ctype.h&gt; //字符处理 #include &lt;errno.h&gt; //定义错误码 #include &lt;float.h&gt; //浮点数处理 #include &lt;fstream.h&gt; //文件输入/输出 #include ...

    C_C++运算中数据类型隐含转换溢出分析

    本文通过一个简单的例子,剖析不同数据类型的存储结构、运算相互转换及转换中可能出现的问题—溢出,提出避免发生溢出的办法,目的是在教学和实践中得到正确结果。

    新手学习C++入门资料

    上面两个都是C风格的强制类型转换,C++还增加了一种转换方式,比较一下上面和下面这个书写方式的不同: long int el=123; short i=int (el); float m=34.56; int i=int (m); 使用强制类型转换的最大好处...

    C++教程网《Linux网络编程》视频百度云地址

    读、写、异常事件发生条件 用select改进回射服务器程序。 15socket编程(十) 用select改进第八章点对点聊天程序 16socket编程(十一) 套接字I/O超时设置方法 用select实现超时 read_timeout函数封装 write...

    Visual C++编程技巧精选500例.pdf

    l97 如何将CString类型转换成loat类型? 198 如何将CString中的字符串赋值给字符指针? 199 如何折行显示字符串? 200 如何旋转显示字符串? 20l 如何显示星期月份字符串? 202 如何显示包括制表符的字符串? 203 如何使用...

    C++ Primer第四版【中文高清扫描版】.pdf

    5.12.1 何时发生隐式类型转换 154 5.12.2 算术转换 155 5.12.3 其他隐式转换 156 5.12.4 显式转换 158 5.12.5 何时需要强制类型转换 158 5.12.6 命名的强制类型转换 158 5.12.7 旧式强制类型转换 160 小结 161 术语 ...

    非常经典的c++ primer视频教程6-10

    5.12.1 何时发生隐式类型转换 5.12.2 算术转换 5.12.3 其他隐式转换 5.12.4 显式转换 5.12.5 何时需要强制类型转换 5.12.6 命名的强制类型转换 5.12.7 旧式强制类型转换 第6章 语句 6.1 简单语句 6.2 声明...

    你必须知道的495个C语言问题

    我试了类型转换,但是不行。 第5章 空指针 空指针和空指针常量 5.1 臭名昭著的空指针到底是什么? 5.2 怎样在程序里获得一个空指针? 5.3 用缩写的指针比较“if(p)”检查空指针是否有效?如果空指针的内部...

    C 语言编程常见问题解答.chm

    什么是总线错误、内存错误和内存信息转储? 7.25 怎样确定一块已分配的内存的大小? 7.26 free()函数是怎样知道要释放的内存块的大小的? 7.27 可以对void指针进行算术运算吗? 7.28 怎样打印一个地址? 第8...

    《你必须知道的495个C语言问题》

    我试了类型转换,但是不行。 52 第5章 空指针 53 空指针和空指针常量 53 5.1 臭名昭著的空指针到底是什么? 53 5.2 怎样在程序里获得一个空指针? 54 5.3 用缩写的指针比较“if(p)”检查空指针是否有效?...

    C语言编程要点

    什么是总线错误、内存错误和内存信息转储? 126 7.25. 怎样确定一块已分配的内存的大小? 126 7.26. free()函数是怎样知道要释放的内存块的大小的? 126 7.27. 可以对void指针进行算术运算吗? 127 7.28. 怎样打印一个...

    C++中的类型转换static_cast、dynamic_cast、const_cast和reinterpret_cast总结

    这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中确实经常使用的。俗话说的好,不懂自己写的代码的程序员,不是好的程序员;如果一个程序员对于自己写的代码都不懂,...

    最新名企标准通用C++面试题,

    2、在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? 答:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为: void foo(int x, int...

Global site tag (gtag.js) - Google Analytics