4 标准转换

4 标准转换4标准转换1、标准转换是为内置类型定义的隐式转换。标准转换序列是按以下顺序定义的标转转换过程:——零或一次以下转换:左值到右值的转换,数组到指针的转换,函数到指针的转换。——零或一次以下转换:整型提升,符点提升,整型转换,符点转换,符点-整型转换,指针转换,成员指针转换,和布尔转换。——零或一

大家好,欢迎来到IT知识分享网。4 标准转换

4 标准转换

1、标准转换是为内置类型定义的隐式转换。标准转换序列是按以下顺序定义的标转转换过程:

       ——零或一次以下转换:左值到右值的转换,数组到指针的转换,函数到指针的转换。

       ——零或一次以下转换:整型提升,符点提升,整型转换,符点转换,符点整型转换,指针转换,成员指针转换,和布尔转换。

——零或一次限定转换。

[注意:标准转换序列可能为空,也就是说,可以不包含转换。] 如果需要,标准转换序列将作用于表达式并将它转换为目的类型。

2[注意:特定类型的表达式将在以下上下文中转换为其他类型:

       ——被用作操作符的操作数。操作符对操作数的要求规定了目标类型。

       ——被用于if语句或重复语句(6.4, 6.5)中的条件。目标类型为bool

       ——被用于switch语句的表达式。目标类型为整型(6.4)。

       ——被用于初始化中的源表达式(包括被用于函数的参数或返回语句)。目标类型为被初始化的实体的类型。参见8.5,

8.5.3
]

3、表达式e能被隐式的转换为类型T当且仅当对于引入的临时变量t8.5),声明“T t=e;”成立。隐式转换的作用等价于执行上述声明和初始化,并将临时变量作为转换的结果。仅当T为引用类型(

8.3.2
)时,转换结果是左值。表达式e仅在初始化过程需要的情况下才用作左值。

4[注意:对于用户定义的类型,将同时考虑用户定义的转换,参见12.3。一般来说,一个隐式的转换序列(

13.3.3
.1
)由标准转换序列+用户定义的转化+标准转换序列组成。

5、在某些情况下,需要屏蔽特定的转换。例如:一元操作符&的操作数需要屏蔽左值右值转换。在具体讨论操作符的时候会列出这些异常情况。]

4.1 左值右值转换

1、非函数、非数组类型T的左值能被转换为右值。如果T为不完全类型,那么进行左值右值转换是不合法的。如果左值对象未初始化,或者其类型不是T,也不是T的子类型,那么进行左值右值转换的结果是未定义的。如果T是一个非class类型,那么右值的类型为T的未cv限定版本,否则,右值的类型为T。(也就是说,只有class类型的右值才可能是cv限定的,因此在C语言中,所有的右值都是未cv限定的。)

2、右值的结果其实就是左值对象包含的值。当左值右值转换发生在sizeof

5.3.3
)的操作数中的时候,并不访问所引用对象的值,因为sizeof操作符不需要对操作数进行计算。

3[注意:可同时参考3.10]

4.2 数组指针转换

1、类型“array of N T”或者“array of unknown bound of T”的左值或右值可被转换为类型“pointer to T”的右值。结果是一个指向数组第一个元素的指针。

2、非宽字符串常量(

2.13.4
)可被转换为 pointer to char 类型的右值;宽字符串常量则应该转换为“pointer to wchar_t”类型的右值。在任何一种情况下,转换结果都等价于指向数组(字符串或宽字符串数组)第一个元素的指针。此转换仅在目标类型是显式的适当指针类型时才进行,对于一般的左值右值转换不起作用[注意:这个转换已经废弃了。参见Annex D]。为了对重载解析(13.3.3.1.1)进行等级评定,这个转换被分解为数组指针转换和限定转换(4.4)两个步骤。[例如:“abc”被转换为“pointer to const char”类型是通过首先转换为“pointer to char”类型,然后再进行限定转换而完成的。]

4.3 函数指针转换

1、函数类型T的左值可被转换为类型“pointer to T”的右值。结果是指向函数的指针。

2[注意:重载函数的转换规则参见13.4]

4.4 限定转换

1、如果cv2>cv1,那么类型“pointer to cv

1
T
”的右值能被转换为类型“pointer to cv2 T”的右值。

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限定符:

       两个指针类型T1T2相似是指存在类型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,jconst, volatile, const volatile或者为空。在一个指针类型中,除第一个之外的其他cv限定符构成的n元组,例如指针类型T1中的cv1,1, cv1,2, …, cv1,n,称为指针类型的cv限定签名。类型为T1的表达式能被转换为T2当且仅当以下条件成立:

——两个指针类型相似。

——对任意的j>0,如果cv1,j包含const那么cv2,j也包含constvolatile类似。

——如果cv1,jcv2,j不相同,那么所有的cv2,k必须包含const,其中0<k<j

[注意:根据上述条件可知不能将T**类型转换为const T**。因为这里T1 is a pointer to a pointer to TT2 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、两个多层成员指针类型或两个多层指针和成员指针混合类型T1T2相似,如果存在类型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类型。

2wchar_t

3.9.1
)类型和枚举类型(7.2)的右值能被转换为以下几种类型的右值:int, unsigned int, long, unsigned long。它们会首先尝试转换为int类型,如果int类型不能表示它们的所有取值,将进一步尝试unsigned int,以此类推。

3、整数位域(9.6)的右值首先尝试转换为int类型,如果int类型无法表示它的所有取值,将尝试转换为unsigned int类型,如果unsigned int类型仍无法表示它的所有取值,将不对其进行提升。如果位域是枚举类型,则按枚举类型的右值进行提升。

4bool类型的右值可被提升为int类型的右值,false对应0true对应1

5、这些转换称为整型提升

4.6 符点提升

1float类型的右值可被转换为double类型的右值。值不变。

2、这个转换称为符点提升

4.7 整型转换

1、一种整型的右值能被转换为另一种整型的右值。枚举类型的右值能转换为整型的右值。

2、如果目标类型是无符号的,目标值是源值模2n的余数(n是用来表示无符号目标类型的位数)。[注意:如果两种类型都用补码表示,那么这个转换只是概念上的,因为在不进行截断的情况下(目标类型的尺寸小于源类型),不需对值做任何改动。]

3、如果目标类型是有符号的,那么当目标类型有足够的位数时(能表示源类型的取值),取值不变。否则,取值由具体的实现定义。

4、如果目标类型为bool,参见4.12。如果源类型为boolfalse转换为0true转换为1

5、如果允许整型提升,则不要进行整型转换。

4.8 符点转换

1、一种符点类型的右值能被转换为另一种符点类型的右值。如果源值能被目标类型精确表示,则转换结果就是这个精确表示。如果源值位于两个相邻的目标值之间,转换结果由编译器在其中选择一个。对于其他情况,转换结果未定义。

2、如果允许符点提升,则不要进行符点转换。

4.9 符点整型转换

1、符点类型的右值可被转换为整型的右值。转换丢弃符点类型的小数部分。如果目标类型无法表示被截取的整数部分,那么结果是未定义的[注意:如果目标类型为bool,参见4.12]

2、整型或枚举类型的右值可被转换为符点类型的右值。如果可能,结果不变。否则,是保存高位部分还是地位部分由具体实现定义。[注意:精度的丢失发现在整型值无法由符点值完整表示的情况下。]如果源类型为boolfalse被转换为0true被转换为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”类型的右值,其中BD的基类(第10章)。如果BD的不可访问(第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”类型的右值,其中DB的派生类(第10章)[比如:double B::* pb = &B::d;  double D::* pd = pb;(其中dBdouble类型成员)]。如果BD的不可访问(第11章)、非确定(10.2)或虚(10.1)基类,那么此类转换是非法的。转换前后指向的都是同一个成员。既然转换结果的类型为“pointer to member of D of type cv T”,所以它能通过D对象而被间接引用[例如:o.*pd = 3.14;(其中oD的对象)],引用的结果指向D实例中的B成员,和通过B的对象间接引用B的成员指针是相同的。空成员指针值被转换为目标类型的空成员指针值。

4.12 布尔转换

1
、算术类型、枚举类型、指针或成员指针类型的右值可被转换为
bool
类型的右值。
0
、空指针,或空的成员指针被转换为
false
;其他的值则转换为
true

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32182.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信