转型运算符

来自cppreference.com
< c‎ | language

进行显式类型转换。

语法

( 类型名 ) 表达式

其中

类型名 - void 类型或任何标量类型
表达式 - 任何标量类型表达式(除非 类型名void ,此情况下它可以是任何表达式)

解释

类型名void ,则 表达式 为其副效应求值,而其返回值被舍弃,与单独将 表达式 用作表达式语句时相同。

否则,若 类型名 恰是 表达式 的类型,则不做任何事(除非若 表达式 拥有浮点类型,且它表示大于其范围和精度的值——见后述)。

否则,转换 表达式 的值被到 类型名 所指名的类型,如下:

允许每种如同赋值的隐式转换

另外还允许显式转换,允许下列转换规则:

  • 任何整数能被转型到任何指针类型。除了如同 NULL 的空指针常量(这不需要转型),结果是实现定义的,可能对齐不准确,可能不指向所引用类型的对象,而且可能是一个陷阱表示
  • 任何指针类型可以被转型到任何整数类型。结果是实现定义的,即使是对空指针值(它们不必得到零值)。若结果不能被表示成目标类型,则行为未定义(无符号整数在从指针转型的情况下不实现模算术)。
  • 任何指向对象的指针能被转型成指向任何其他对象类型的指针。若其值未为目标类型正确对齐,则行为未定义。否则,若其值转换回原类型,则它与原值比较相等。若指向对象指针被转型到指向任何字符类型的指针,则结果指向对象的最低字节,且能自增到目标类型的 sizeof (换言之,可用于检验对象表示,或通过 memcpymemmove 复制)。
  • 任何指向函数的指针能被转型成指向任何其他函数类型的指针。若转换结果指针回原类型,则它与原值比较相等。若将转换所得指针用作函数调用,则行为未定义(除非函数类型兼容)。
  • 在指针间转换(指向对象或指向函数的)时,若原值是其类型的空指针值,则结果是目标类型的正确空指针值。

在任何场合(执行隐式转换和同类型转型时)中,若 表达式类型名 是浮点类型,且 表达式 表示大于其类型所指示的范围和精度(见 FLT_EVAL_METHOD ),则剥除范围和精度以匹配目标类型。

转型表达式的值类别始终是非左值。

注解

因为 constvolatilerestrict_Atomic 限定符仅对左值有效,到 cvr 限定或原子类型的转型准确等价于到对应无无限定类型的转型。

转型到 void 在令编译器关于未使用结果的警告沉默时有用。

不允许不列于此的转换。特别是,

  • 没有指针和浮点类型间的转换
  • 没有指向函数指针和指向对象指针(含 void* )间的转换

若实现提供 intptr_t 与/或 uintptr_t,则从指向对象类型(包括 cv void)的指针到这些类型的转型始终为良定义。然而这对于函数指针并不保证。

(C99 起)

注意函数指针与对象指针间的转换被许多编译器作为扩展接受,并且为 POSIX dlsym() 函数的一些用法所期待。

示例

#include <stdio.h>
 
int main(void)
{
    // 检验对象表示是转型的合法使用
    double d = 3.14;
    printf("The double %.2f(%a) is: ", d, d);
    for(size_t n = 0; n < sizeof d; ++n)
        printf("0x%02x ", ((unsigned char*)&d)[n]);
 
    // edge cases
    struct S {int x;} s;
//    (struct S)s; // 错误;非标量类型
                   // 尽管转型到相同类型什么都不做
    (void)s; // 转换任何类型到 void 都 OK
}

可能的输出:

The double 3.14(0x1.91eb851eb851fp+1) is: 0x1f 0x85 0xeb 0x51 0xb8 0x1e 0x09 0x40

引用

  • C17 标准(ISO/IEC 9899:2018):
  • 6.5.4 Cast operators (第 65-66 页)
  • C11 标准(ISO/IEC 9899:2011):
  • 6.5.4 Cast operators (第 91 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 6.5.4 Cast operators (第 81 页)
  • C89/C90 标准(ISO/IEC 9899:1990):
  • 3.3.4 Cast operators

参阅