由于math.h同时声明了int isnan(double x)int isnanf(float x),我预计下面的代码在与gcc -O0 -Wall -Wextra -Wpedantic -Wconversion -Wdouble-promotion一起编译时会生成某种"Float to Double Promotion"警告.然而,事实并非如此.为何会是这样呢?

#include <stdio.h>
#include <math.h>

int main()
{
  float x = 1.23f;
  printf("%s\n", isnan(x) ? "nan" : "number");
  return 0;
}

推荐答案

因为math.h同时声明了int isnan(double x)int isnanf(float x)

是吗?C语言规范只记录了支持所有浮点类型的ANisnan() macro.如果实现提供了一个接受类型double的参数的isnan()函数,那么我预计它会被一致性实现中的宏所隐藏.

我预计下面的代码在用gcc -O0 -Wall -Wextra -Wpedantic -Wconversion -Wdouble-promotion编译时会生成某种"Float to Double Promotion"警告.然而,事实并非如此.为何会是这样呢?

因为isnan()宏支持所有浮点类型,而您的宏在执行此操作时不需要进行会引发此类警告的转换.下面是一个作为类型泛型宏的合理实现:

#define isnan(x) _Generic((x), \
    long double: isnanl,       \
    default: isnan,            \
    float: isnanf              \
)(x)

(这假设指定的函数是可用的,包括isnan(double)个,但C语言并不要求这样做.)

泛型 Select 和定义类型泛型宏的能力是C11中的新功能.因此,如果您为该标准的早期版本 Select 严格一致性模式,那么得到一个实际执行某种类型转换的版本也就不足为奇了.

C++相关问答推荐

C strlen on char array

C指针地址和转换

通过MQTT/蚊子发送大文件—限制在4MB

getchar读css + z还是返回css?

VS代码C/C++扩展intellisense无法检测环境特定函数'

Ebpf内核代码:permission denied:invalid access to map value

返回一个包含数组的 struct

拥有3x3二维数组并访问数组[1][3]等同于数组[2][0]?

_泛型控制表达式涉及数组碰撞警告的L值转换错误?

如何识别Linux中USB集线器(根)和连接到集线器(根设备)的设备(子设备)?

如何在STM8项目中导入STM8S/A标准外设库(ST VisualDeveloper)?

这个计算C中阶乘的函数正确吗?

C指针概念分段故障

指向不同类型的指针是否与公共初始序列规则匹配?

如何在C++中安全地进行浮点运算

静态初始化顺序失败是否适用于C语言?

为什么GCC 13没有显示正确的二进制表示法?

解密Chrome加密密钥

计算时出现奇怪的计算错误;N Select K;在C中

使用邻接表创建图