ANSI C中的整型进级
副标题#e#
ANSI C中的整型进级
char,short int可能int型位段(bit-field),包罗它们的有标记或无标记变型,以及列举范例,可以利用在需要int或unsigned int的表达式中,假如int可以完整地暗示源范例的所有值,那么该范例的值就转换为int,不然转换为unsigned int。
ANSI C中的寻常算术转换
当执行算术运算时,操纵数的范例假如差异,就会产生转换。
数据范例一般朝着浮点精度更高、长度更长的偏向转换,整型数假如转换为signed不会丢失信息,就转换为signed,不然就转换为unsigned。
这个称为值保存(value preserving)原则,与K&R C所回收的无标记保存(unsigned preserving)原则差异。
浮点类:
假如一个操纵数的范例是long double,那么另一个操纵数无论是什么范例都将被转换成long double。
假如两个操纵数都不是long double型,那么当个中一个操纵数的范例是double型,则另一个就将被转换成double 型。
假如两个操纵数都不是double型,而个中一个操纵数是float型,则另一个被转换成float型。
留意:double和float都不行用unsigned,short修饰,别的float还不行用long修饰
整形类规:
不然,两个操纵数都不是三种浮点范例之一,它们必然是某种整值范例。在确定配合的方针晋升范例之前,编译器将在所有小于int的整值范例上施加一个被称为整值晋升(integral promotion)的进程。在举办整值晋升时,范例(char、signed char、unsigned char和short、int)都被晋升为范例int。假如呆板上的int型足够暗示所有unsigned、shoft型的值(这凡是产生在short用半个字暗示,而int用一个字暗示的环境下),则unsigned short int也被转换成int,不然它会被晋升为unsigned int。
wchar_t和列举范例被晋升为可以或许暗示其底层范例(underlying type)所有值的最小整数范例。
一旦整值晋升执行完毕,范例较量就又一次开始。假如一个操纵数是unsigned long型,则第二个也被转换成unsigned long型。假如两个操纵数的范例都不是unsigned long,而个中一个操纵数是long型,则另一个也被转换成long型。long 范例的一般转换有一个破例,假如一个操纵数是long型,而另一个是unsigned int型,那么只有呆板上的long型足够长,以便可以或许存放unsigned int的所有值时(一般来说,在32位操纵系统中,long型和int 型都用一个字长来暗示,所以不满意这里的假设条件),unsigned int才会被转换为long型,不然两个操纵数都被晋升为unsigned long型。若两个操纵数都不是long型,而个中一个是unsigned int型,则另一个也被转换成unsigned int 型。不然两个操纵数必然都是int 型。
int d = -1;
if (d <= sizeof(arr)/sizeof(arr[0]))
…
这样的较量语句有问题,sizeof运算符返回无标记数。
if语句在signed int和unsigned int之间测试相等性,凭据上面的说法,可以这样表明:
首先,signed int和unsigned int长度沟通,不会向更长的偏向转换。
其次,signed int不能完整地暗示unsigned int的所有值。
因此,signed int d被转换为unsigned int范例。
这样,-1就酿成一个很是庞大的正整数,导致较量功效与预期的不符。
办理的要领是利用强制转换,(int)(sizeof(arr)/sizeof(arr[0]))。
我在VC++ 6.0和DEV-C++ 4.9.9.0中实验了上面那段代码,简直如此。
不要因为无标记数不存在负值而用它暗示数量(如年数、国债等),只管利用int之类的有标记数,这样在殽杂运算中,这样就不必担忧界线环境(如-1被翻译为很是大的正数)。
只有在利用位段和二进制掩码时,才利用无标记数。
应该在表达式中利用强制范例转换,使所有的操纵数均为有标记数或无标记数,这样就不必由编译器来选择功效的范例。
#p#副标题#e#
C语言中的范例转换比一般人想象中的要遍及得多。
在涉及范例小于int或double的表达式中,都有大概呈现范例转换。
printf(" %d ", sizeof ‘A’);
的功效是4, 是int的长度,编译器首先将’A’进级为整数97,再挪用sizeof。
整型晋升就是char、short int和位段范例(无论signed或unsigned)以及列举范例将被晋升为int,前提是int 可以或许完整地容纳原先的数据,不然将被转换为unsigned int。
ANSI C暗示,假如编译器可以或许担保运算功效一致,也可以省略范例晋升——这凡是呈此刻表达式中存在常量操纵数的时候。
另一个会产生隐式范例转换的处所就是参数通报。
在K&R C中,由于函数的参数也是表达式,所以也会产生范例晋升。
在ANSI C中,假如利用了适当的函数原型,范例晋升便不会产生,不然也会产生。
在被挪用函数的内部,晋升后的参数被减少为原先声明的巨细。
这就是为什么单个的printf()名目字符串%d能合用于几个差异范例,
short、char或int,而岂论实际通报的是上述范例的哪一个。
函数从仓库中(或寄存器中)取出的参数老是int类,并在printf或其他被挪用函数里按统一的名目处理惩罚。
printf是一个可变参数函数,此时一般的参数晋升始终会产生。