C 中带条件运算符的表达式的类型是什么?
What is the type of an expression with a conditional operator in C?
假设我们有以下表达式:
(x>y) ? printf("type of int") : func_string()
那么我们这里有什么?
x>y -> true -> printf("type of int") -> the type of the expression is int (because printf function is an int type function).
或
x>y -> false -> calls func_string() function which for the purpose of the question, returns a string.
结论是对于这个表达式的结果我们只有 2 个选项:
一个 int function (prinf)
或一个字符串 function (func_string)
.
这意味着表达式有 2 种可能的类型。
然而,编译器不能真正等到运行时间来获取表达式的类型,编译器不能在不确定表达式的类型是否为 int 的情况下真正编译代码或字符串,如果我们尝试 运行 这种代码,条件运算符的 2 个结果有 2 种不同的类型,我们会得到编译错误吗?
标准 C17 6.5.15 指定操作数必须根据以下行为:
Constraints
The first operand shall have scalar type.
One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object type and the other is a pointer to a qualified or
unqualified version of void.
在您的示例中,(x>y) ? printf("type of int") : func_string();
、printf
returns 类型 int
是算术类型。 func_string()
按理说是returns一个char*
,也就是指针类型。此用例与上面列出的任何有效场景都不匹配,因为类型不兼容。
因此编译器报告代码无效 C。编译器诊断的一些示例:
icc:
operand types are incompatible ("int" and "char *")
gcc:
pointer/integer type mismatch in conditional expression
如果第 2 个和第 3 个操作数 兼容或至少两种算术类型(一个 float
和一个 int
等),那么这6.5.15 的规则适用:
If both the second and third operands have arithmetic type, the result type that would be
determined by the usual arithmetic conversions, were they applied to those two operands,
is the type of the result. If both the operands have structure or union type, the result has
that type. If both operands have void type, the result has void type.
要理解该部分,您需要理解常用算术转换的含义,请参阅
最重要的是,?:
并不是一些美化的 if-else
替代品,而是一个带有许多特殊规则的相当奇特的运算符。 ?:
在实际 C 代码中也只有很少的有效用例,它的少数有效用途之一是某些类似函数的宏。
假设我们有以下表达式:
(x>y) ? printf("type of int") : func_string()
那么我们这里有什么?
x>y -> true -> printf("type of int") -> the type of the expression is int (because printf function is an int type function).
或
x>y -> false -> calls func_string() function which for the purpose of the question, returns a string.
结论是对于这个表达式的结果我们只有 2 个选项:
一个 int function (prinf)
或一个字符串 function (func_string)
.
这意味着表达式有 2 种可能的类型。
然而,编译器不能真正等到运行时间来获取表达式的类型,编译器不能在不确定表达式的类型是否为 int 的情况下真正编译代码或字符串,如果我们尝试 运行 这种代码,条件运算符的 2 个结果有 2 种不同的类型,我们会得到编译错误吗?
标准 C17 6.5.15 指定操作数必须根据以下行为:
Constraints
The first operand shall have scalar type.
One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object type and the other is a pointer to a qualified or
unqualified version of void.
在您的示例中,(x>y) ? printf("type of int") : func_string();
、printf
returns 类型 int
是算术类型。 func_string()
按理说是returns一个char*
,也就是指针类型。此用例与上面列出的任何有效场景都不匹配,因为类型不兼容。
因此编译器报告代码无效 C。编译器诊断的一些示例:
icc:
operand types are incompatible ("int" and "char *")
gcc:
pointer/integer type mismatch in conditional expression
如果第 2 个和第 3 个操作数 兼容或至少两种算术类型(一个 float
和一个 int
等),那么这6.5.15 的规则适用:
If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.
要理解该部分,您需要理解常用算术转换的含义,请参阅
最重要的是,?:
并不是一些美化的 if-else
替代品,而是一个带有许多特殊规则的相当奇特的运算符。 ?:
在实际 C 代码中也只有很少的有效用例,它的少数有效用途之一是某些类似函数的宏。