大家好,欢迎来到IT知识分享网。
4 标准转换
1、标准转换是为内置类型定义的隐式转换。标准转换序列是按以下顺序定义的标转转换过程:
——零或一次以下转换:左值到右值的转换,数组到指针的转换,函数到指针的转换。
——零或一次以下转换:整型提升,符点提升,整型转换,符点转换,符点–整型转换,指针转换,成员指针转换,和布尔转换。
——零或一次限定转换。
[注意:标准转换序列可能为空,也就是说,可以不包含转换。] 如果需要,标准转换序列将作用于表达式并将它转换为目的类型。
2、[注意:特定类型的表达式将在以下上下文中转换为其他类型:
——被用作操作符的操作数。操作符对操作数的要求规定了目标类型。
——被用于if语句或重复语句(6.4, 6.5)中的条件。目标类型为bool。
——被用于switch语句的表达式。目标类型为整型(6.4)。
——被用于初始化中的源表达式(包括被用于函数的参数或返回语句)。目标类型为被初始化的实体的类型。参见8.5,
8.5.3
3、表达式e能被隐式的转换为类型T当且仅当对于引入的临时变量t(8.5),声明“T t=e;”成立。隐式转换的作用等价于执行上述声明和初始化,并将临时变量作为转换的结果。仅当T为引用类型(
8.3.2
4、[注意:对于用户定义的类型,将同时考虑用户定义的转换,参见12.3。一般来说,一个隐式的转换序列(
13.3.3
5、在某些情况下,需要屏蔽特定的转换。例如:一元操作符&的操作数需要屏蔽左值–右值转换。在具体讨论操作符的时候会列出这些异常情况。]
4.1 左值–右值转换
1、非函数、非数组类型T的左值能被转换为右值。如果T为不完全类型,那么进行左值–右值转换是不合法的。如果左值对象未初始化,或者其类型不是T,也不是T的子类型,那么进行左值–右值转换的结果是未定义的。如果T是一个非class类型,那么右值的类型为T的未cv限定版本,否则,右值的类型为T。(也就是说,只有class类型的右值才可能是cv限定的,因此在C语言中,所有的右值都是未cv限定的。)
2、右值的结果其实就是左值对象包含的值。当左值–右值转换发生在sizeof(
5.3.3
3、[注意:可同时参考3.10]
4.2 数组–指针转换
1、类型“array of N T”或者“array of unknown bound of T”的左值或右值可被转换为类型“pointer to T”的右值。结果是一个指向数组第一个元素的指针。
2、非宽字符串常量(
2.13.4
4.3 函数–指针转换
1、函数类型T的左值可被转换为类型“pointer to T”的右值。结果是指向函数的指针。
2、[注意:重载函数的转换规则参见13.4。]
4.4 限定转换
1、如果cv2>cv1,那么类型“pointer to cv
1
2、如果cv2>cv1,那么类型“pointer to member of X of type cv1 T”的右值能被转换为类型“pointer to member of X of type cv2 T”的右值。
3、[注意:函数类型(包括那些指向成员函数类型的指针)不能被cv限定(
8.3.5
4、在多层指针类型中,转换能够按照下面的规则给除第一层以外的其他层添加cv限定符:
两个指针类型T1和T2相似是指存在类型T和整数n > 0,满足:
T1 is cv1,0 pointer to cv1,1 pointer to … cv1,n-1 pointer to cv1,n T
和
T2 is cv2,0 pointer to cv2,1 pointer to … cv2,n-1 pointer to cv2,n T
其中每一个cvi,j为const, volatile, const volatile或者为空。在一个指针类型中,除第一个之外的其他cv限定符构成的n元组,例如指针类型T1中的cv1,1, cv1,2, …, cv1,n,称为指针类型的cv限定签名。类型为T1的表达式能被转换为T2当且仅当以下条件成立:
——两个指针类型相似。
——对任意的j>0,如果cv1,j包含const那么cv2,j也包含const,volatile类似。
——如果cv1,j和cv2,j不相同,那么所有的cv2,k必须包含const,其中0<k<j。
[注意:根据上述条件可知不能将T**类型转换为const T**。因为这里T1 is a pointer to a pointer to T;T2 is a pointer to a pointer to const T。可见,除了cv2,2 = const外,其他的限定符都为空。因而,cv2,2 != cv1,2,根据最后一个条件,cv2,1必须为const,显然不符合。如果T**类型转换为const T**(也就是说,允许以下代码中的//1行),那么将导致程序能够修改一个const对象(如//2行所示):
int main() {
const char c = ’c’;
char* pc;
const char** pcc = &pc; //1: not allowed
*pcc = &c;
*pc = ’C’; //2: modifies a const object
}
]
5、多层成员指针类型,或多层的指针和成员指针混合类型具有如下形式:
cv0 P0 to cv1 P1 to . . . cvn−1 Pn−1 to cvn T
其中Pi为指针或成员指针,T为非指针类型或成员指针类型。
6、两个多层成员指针类型或两个多层指针和成员指针混合类型T1和T2相似,如果存在类型T和整数n>0,满足:
T1 is cv1 , 0 P0 to cv1 , 1 P1 to . . . cv1 ,n − 1 Pn − 1 to cv1 ,n T
和
T2 is cv2 , 0 P0 to cv2 , 1 P1 to . . . cv2 ,n − 1 Pn − 1 to cv2 ,n T
7、对于相似的多层成员指针类型和多层指针和成员指针混合类型,添加cv限定符的规则同相似指针类型的规则相同。
4.5 整型提升
1、类型char, signed char, unsigned char, short int,和unsigned short int的右值可被转换为类型int的右值,如果int类型能源类型的所有取值;否则,这些源右值类型被转换为unsigned int类型。
2、wchar_t(
3.9.1
3、整数位域(9.6)的右值首先尝试转换为int类型,如果int类型无法表示它的所有取值,将尝试转换为unsigned int类型,如果unsigned int类型仍无法表示它的所有取值,将不对其进行提升。如果位域是枚举类型,则按枚举类型的右值进行提升。
4、bool类型的右值可被提升为int类型的右值,false对应0,true对应1。
5、这些转换称为整型提升。
4.6 符点提升
1、float类型的右值可被转换为double类型的右值。值不变。
2、这个转换称为符点提升。
4.7 整型转换
1、一种整型的右值能被转换为另一种整型的右值。枚举类型的右值能转换为整型的右值。
2、如果目标类型是无符号的,目标值是源值模2n的余数(n是用来表示无符号目标类型的位数)。[注意:如果两种类型都用补码表示,那么这个转换只是概念上的,因为在不进行截断的情况下(目标类型的尺寸小于源类型),不需对值做任何改动。]
3、如果目标类型是有符号的,那么当目标类型有足够的位数时(能表示源类型的取值),取值不变。否则,取值由具体的实现定义。
4、如果目标类型为bool,参见4.12。如果源类型为bool,false转换为0,true转换为1。
5、如果允许整型提升,则不要进行整型转换。
4.8 符点转换
1、一种符点类型的右值能被转换为另一种符点类型的右值。如果源值能被目标类型精确表示,则转换结果就是这个精确表示。如果源值位于两个相邻的目标值之间,转换结果由编译器在其中选择一个。对于其他情况,转换结果未定义。
2、如果允许符点提升,则不要进行符点转换。
4.9 符点整型转换
1、符点类型的右值可被转换为整型的右值。转换丢弃符点类型的小数部分。如果目标类型无法表示被截取的整数部分,那么结果是未定义的[注意:如果目标类型为bool,参见4.12]
2、整型或枚举类型的右值可被转换为符点类型的右值。如果可能,结果不变。否则,是保存高位部分还是地位部分由具体实现定义。[注意:精度的丢失发现在整型值无法由符点值完整表示的情况下。]如果源类型为bool,false被转换为0,true被转换为1。
4.10 指针转换
1、空指针常量是一个整型常量表达式(5.19)右值,其值为0。空指针常量可被转换为指针类型;结果为相应指针类型的空指针值,并且有别于那些不是从空指针常量创建的其他指针。两个相同类型的空指针值相等。将空指针常量转换为cv限定的指针类型是单步转换,而不是一个指针转换和一个限定转换(4.4)组成的序列。
2、对于对象类型T,“pointer to cv T”类型的右值可被转换为“pointer to cv void”类型的右值,上述转换的结果指向T类型对象所驻留空间的起始位置,就像对象是T类型的主要派生对象一样(也就是说,不是基类子对象)。
3、对于class类型D,“pointer to cv D”类型的右值可被转换为“pointer to cv B”类型的右值,其中B为D的基类(第10章)。如果B是D的不可访问(第11章)基类或非确定的基类(10.2),那么包含此类转换的程序是非法程序。转换结果为指向此派生类对象的基类子对象的指针。空指针值被转换为目标类型的空指针值。
4.11 成员指针转换
1、空指针常量(4.10)可被转换为成员指针类型;其结果为相应成员指针类型的空成员指针值,并且有别于那些不是从空指针常量创建的其他成员指针。两个相同类型的空成员指针值相等。将空指针常量转换为cv限定的成员指针类型是单步转换,而不是一个成员指针转换和一个限定转换(4.4)组成的序列。
2、对于class类型B,“pointer to member of B of type cv T”类型的右值可被转换为“pointer to member of D of type cv T”类型的右值,其中D是B的派生类(第10章)[比如:double B::* pb = &B::d; double D::* pd = pb;(其中d是B的double类型成员)]。如果B是D的不可访问(第11章)、非确定(10.2)或虚(10.1)基类,那么此类转换是非法的。转换前后指向的都是同一个成员。既然转换结果的类型为“pointer to member of D of type cv T”,所以它能通过D对象而被间接引用[例如:o.*pd = 3.14;(其中o为D的对象)],引用的结果指向D实例中的B成员,和通过B的对象间接引用B的成员指针是相同的。空成员指针值被转换为目标类型的空成员指针值。
4.12 布尔转换
1
、算术类型、枚举类型、指针或成员指针类型的右值可被转换为
bool
类型的右值。
0
、空指针,或空的成员指针被转换为
false
;其他的值则转换为
true
。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32182.html