printf("%d\n", (1 ? (int)1 : (double)1.1));
结果不是 1,而是一个随机整数(在 Windows10 上的 wsl 上运行)。比如
-2031766944
201011808
当我想使用以下方式实现动态或重叠变量时,我发现这个问题:
typedef enum _DataType
{
INT,
DOUBLE
} DataType;
typedef union _Data
{
int int_;
double dou_;
} Data;
typedef struct _Number
{
DataType datatype;
Data data;
} Number;
因为C是静态类型。没有函数可以获取
Number
的实际值。所以我尝试了这样的宏函数:
#define GETVAL(param) (((param).datatype == INT) ? (param).data.int_ : (param).data.dou_)
但是该函数似乎只能返回double类型。而我在调试的时候,发现了上面的问题。
在 C 语言中,三元条件运算符
(?:)
的形式为:
condition ? expression_if_true : expression_if_false
关键点是
expression_if_true
和 expression_if_false
都必须产生兼容的类型。如果类型不同,则应用“常规算术转换”将它们转换为通用类型。
在你的例子中:
(0 ? (int)1 : (double)1.1)
由于
0
为 false,因此表达式的计算结果为 (double)1.1
。两种可能的表达是 (int)1
和 (double)1.1
。由于类型提升规则:
当
int
和 double
用于同一表达式时,int
会提升为 double
。
因此,三元表达式的整体类型为
double
。
此外,您在
%d
中使用 printf
作为格式说明符,它需要 int
。但是,由于三元运算符中的类型提升,您传递的是双精度值。
这种不匹配会导致未定义的行为,因为
printf
读取堆栈(或寄存器,具体取决于调用约定),期望得到 int
,但这些位对应于 double
。这会导致垃圾输出或随机整数。
确保类型一致性:确保值的类型与
printf
中的格式说明符匹配。
使用适当的格式说明符:如果结果是
double
,请在 %f
中使用 %lf
或 printf
。
printf("%f ", (0 ? (双)1 : (双)1.1));
或者,如果您总是想要
int
:
printf("%d\n", (0 ? 1 : (int)1.1));
关于你的宏
#define GETVAL(param) (((param).datatype == INT) ? (param).data.int_ : (param).data.dou_)
根据三元运算符的规则,如果
(param).data.dou_
是double
,并且(param).data.int_
是int
,则int
将提升为double
。因此,GETVAL(param)
将始终返回 double
。
每种类型都有单独的宏或函数,根据情况使用适当的宏
param.datatype
#define GETVAL_INT(param) ((param).data.int_)
#define GETVAL_DOUBLE(param) ((param).data.dou_)