1.关于位图的自描述能力
图标或者图形是一种小型的位模式映射于屏幕产生的图像,
实际上,其实就是用原本十六进制表示的位图数组,表示为二进制方式分解方式。例如:
0x07c6,二进制就是0000011111000110,即oxo7c6 = (((((((((((((((((0) * 2 + 0) * 2 + 0) * 2 + 0) * 2 + 0) * 2 + 0) * 2 + 1)* 2 + 1)* 2 + 1)* 2 + 1)* 2 + 1)* 2 + 0)* 2 + 0)* 2 + 0)* 2 + 1)* 2 + 1)* 2 + 0)
我们进行如下宏定义:
#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0
则0x07c6实际表示为:s _ _ _ _ _ X X X X X _ _ _ X X _
通过这种方式,可以让位图有自我描述能力。
2.关于原型
实际上,C语言除了寻常算数转换(即不同类型的操作数做类型提升),它的类型转换比一般人想象的要广泛的多,在设计小于int,double的表达式中,都可能发生类型转换。
在表达式中,小于int类型的数据类型,都会被提升为int,这个特性被称为类型提升。ANSIC对两个小于int的类型进行加法时,都会对两个类似进行类型提升,然后对两个int进行加法,再对结果进行裁剪,如果两个操作数相加不会发生溢出异常,那么实际执行时只需要产生小于int类型的运算结果,可以省略类型提升。类似的,float和double。
常见的类型提升有,char,位段,枚举,unsigned char,short,unsigned short,float,任何数组。前提是int能够容纳原先的数据,否则,提升为unsigned int。
注意:参数也会被提升。
因此,在隐式转化方面,要注意三点:
1.隐式转换是语言中的一种临机手段,方便编译器简化。把所有数据转换为同一的长度,极大的简化了代码的生成,这样,压栈的参数都是同一长度,运行时系统只需要知道参数的数目。
2.缺省的隐式转换,不影响正常编程。
3.隐式转换在设计原型的上下文中,非常重要。
K & R C的函数声明和定义:
声明:
int fun();
定义:
int fun(a,b)
int a;
int b;
{
}
ANSI C:
原型:
int fun(int a,int b);
或
int fun(int,int);
定义
int fun(int a,int b)
{
}
由于有上亿行的C代码采用K&R C方式编程,ANSI C并没有明确规定在函数声明中使用空括号是被正式废弃的,也没有说明继续使用这种版本的形式会导致与未来版本不兼容。因此,这两种风格都会大量存在。
在K&R C风格的函数中传递一个短于int类型的整数,函数实际收到的是int类型,这叫整形提升,这样做的目的,早期是为了简化编译器的工作。同样,传递float类型的参数自动提升为double类型。但在被调用的函数体内,这些类型又被裁剪为相应的类型。这样所有的东西都是相同的长度,大大简化传参过程。注意:早起的编译器,只允许三种类型做参数,int,double,指针,因此,在传递参数时会发生类型提升,但在函数体内,根据函数定义时申明的形参类型,自动裁剪。
相反,如果使用ANSI C 的函数原型。则不进行这样的提升和裁剪,因为假定参数是准确声明的。那么,在K&C和ANSI C的函数使用中,如果使用混合方式,则可能会出现错误。
这两种情况,在使用较窄的类型时,都会失败。