It's our wits that make us men.

VC调试经验

Posted on By CQR

1.VC中是用补码的形式来存储整型数据。用补码的好处是CPU只需用加法器即可实现整数的加减法运算。具体分析有两点:

一.[X+Y]补 = [X]补 + [Y]补

随便写一个计算式,16 + (-8) = ? 16的二进制表示是 00010000,所以用直觉表示法,加法就要写成:

 00010000

+10001000

---------

 10011000

可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,在这种情况下,正常的加法规则不适用于正数与负数的加法,因此必须制定两套运算规则,一套用于正数加正数,还有一套用于正数加负数。从电路上说,就是必须为加法运算做两种电路。 现在,再来看2的补码表示法。

  00010000

+11111000

---------

100001000

可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高的第9位是一个溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8) 的正确答案。这说明了,2的补码表示法可以将加法运算规则,扩展到整个整数集,从而用一套电路就可以实现全部整数的加法。

二.[X-Y]补 = [X]补 - [Y]补 = [X]补 + [-Y]补

从上式可以看出,用补码可以将减法转化成加法运算。举一个例子:

4-(-3)=0100-1101=0100+0011=0111=7

4 - 3 =0100-0011=0100+1101=0001=1

-3-4 =1101-0100=1101+1100=1001=-7

可以看出,编译器只需把被减数做补码运算取反加一(不管被减数是正数还是负数),即可将减法转化成加法运算。

2.在VC中的整数加减法运算,不管是signed还是unsigned,编译器都是以一样的方式做运算。举一个例子:

short  bin3,bin4,bin5;
unsigned short bin8,bin9,bin10;

bin9=63000;
bin10=10000;
bin8=bin9-bin10;
printf("bin8=%d,bin8在内存中的十六进制值=%x\n",bin8,*(unsigned short*)(&bin8));

bin3=63000;
bin4=10000;![](http://i.imgur.com/tic67Gx.png)
bin5=bin3-bin4;
printf("bin5=%d,bin5在内存中的十六进制值=%x\n",bin5,*(short*)(&bin5));

打印结果如下:

signed和unsigned这两种类型的整数相减的结果在内存中的值都是cf08。这说明编译器是以一样的方式做运算。下面这个也能看出来:

signed: -3-1 =1101-0001=1101+1111=1100=-4

unsigned:13-1 =1101-0001=1100=12

因此,signed和unsigned对于计算机来说是无区别,计算机不会管输入进来的整数是signed还是unsigned,它只负责把二进制 数按照设计好的方式做运算。但是作为程序员,我们针对一个具体的应用,必须要明确知道数据是signed还是unsigned。

在VC中,signed short表示整数的范围是0-65535,unsigned short表示整数的范围是-32768-32767。尽管它们在计算机中运算无区分,但在判断数值大小时,编译器会根据是signed还是unsigned做出区分处理。

signed short  bin3;
unsigned short  bin4;
bin3  =40000; 
if(bin3>10000)
	 bin3=10000;
bin4  =40000; 
if(bin4>10000)
	 bin4=10000;

其实,我们可以不必理会计算机对signed和unsigned的处理机制,只需根据现实的需求,定义好数据类型,计算机就会给出符合数学逻辑的结果。

3.VC做两个整数相加减运算时不会做超出最大值的溢出处理。

short  bin3,bin4,bin5;
bin3=23000;
bin4=10000;
bin5=bin3+bin4;

这个出来的结果不会卡在16bit signed能表示的最大值32767。结果是-32536。

4.在VC中的整数乘法运算,编译器会根据被乘数与乘数的符号类型(signed和unsigned)做出不同的处理:

signed short  bin3;
unsigned short  bin4;
signed int   bin6;
unsigned int   bin7;
unsigned short bin8;

bin3=0xcd57;
bin4=0x56;
bin6=bin3*bin4;
printf("bin6=%d,bin6在内存中的十六进制值=%x\n",bin6,*(signed int*)(&bin6));

bin8=0xcd57;
bin4=0x56;
bin7=bin8*bin4;
printf("bin7=%d,bin7在内存中的十六进制值=%x\n",bin7,*(unsigned int*)(&bin7));

打印结果如下:

这个结果与TRITAN DSP乘法器的运算结果是一样的。这也说明TRITAN DSP乘法器的运算逻辑和x86平台乘法器的是一致的。

signed*unsigned的计算过程如下:

Step1 : 因为被乘数为负数,因此硬件会先将 cd57H 求补得到 32A9H。

Step2 : 实现 32a9H*56H=1104c6H

Step3 : 将结果再求补:Result=NOT(1104C6H)+1=FF FFEE FB3AH

unsigned*unsigned的计算过程如下:

Step1 : 实现 CD57H*56H=44 FB3AH

Step2 : 结果 Result=00 0044 FB3AH

从上面的运算过程也能看出,CPU中只有一个乘法逻辑,只是根据符号类型看是否要做补码运算。

5.补码的概念只存在整数中,浮点数float都是原码。

6.使用这个函数hSearch=FindFirstFile(“txt\*.txt”,&fd); 必须设置如下:

否则编译器找不到txt\*.txt,获取不了第一个文件句柄。

7.定义指针必须要给它赋地址值。

8.不能把未赋值的局部变量赋值给其它变量。

9.用C语言+WIN32 API可以开发出图形界面的window application程序。WIN32 API中的窗口类不是C++意义上的类。