C 标准库 - <errno.h>和<float.h>详解

目录

简介

常见库宏

简介

常见库宏


<errno.h>

简介

<errno.h>头文件定义了一个名为errno的全局变量,用于表示最近发生的错误代码。errno是一个整数变量,它的值通常是一个非零的错误代码,用于指示发生了什么类型的错误。也可以在适当的时候修改它的值或重置为零。

<errno.h>头文件还定义了一些常量,这些常量代表不同类型的错误代码。这些常量可以在程序中与errno的值进行比较,以确定发生了哪种类型的错误。

以下是一些常见的errno常量:

  • EDOM:表示数学域错误,例如对负数求平方根。
  • ERANGE:表示结果超出范围,例如对一个超出整型范围的数进行计算。
  • EACCES:表示权限被拒绝,例如试图以只读方式打开一个只有写权限的文件。
  • ENOENT:表示文件或目录不存在。
  • EINVAL:表示无效的参数,例如传递给函数的参数值不符合预期。

常见库宏

1、extern int errno:

这是一个全局变量,类型为int,用于表示最近发生的错误代码。它通过系统调用设置,在某些库函数中指示发生了什么类型的错误。在程序启动时,errno的初始值通常为0。当发生错误时,特定的库函数会修改errno的值为非零值,以表示不同类型的错误。errno是可更改的左值,因此可以通过程序来读取和修改它的值。

2、EDOM:

这个宏表示数学域错误。当某个数学函数的输入参数超出了该函数定义的域时,就会发生域错误。例如,对负数求平方根或对负数进行对数运算都会导致域错误。当发生域错误时,errno会被设置为EDOM。

3、ERANGE:

这个宏表示范围错误。当某个数学函数的输入参数超出了该函数定义的范围时,就会发生范围错误。例如,对一个超出整型范围的数进行计算可能导致范围错误。当发生范围错误时,errno会被设置为ERANGE。

这些宏提供了一种标准化的方式来表示不同类型的错误,并且可以帮助程序员在错误处理过程中进行识别和处理。通过检查errno的值,可以确定特定函数调用是否发生了错误,并根据需要采取适当的措施。

实例

以下是一个简单的代码示例,演示了如何使用<errno.h>头文件中定义的宏来检测和处理错误:

cpp 复制代码
#include <stdio.h>
#include <errno.h>
#include <math.h>

int main() {
    double x = -1.0;
    double result = sqrt(x);
    
    if (errno == EDOM) {
        printf("sqrt(%f) 发生域错误\n", x);
    } else if (errno == ERANGE) {
        printf("sqrt(%f) 发生范围错误\n", x);
    } else {
        printf("sqrt(%f) = %f\n", x, result);
    }
    
    return 0;
}

在这个示例中,我们尝试对负数进行平方根运算。由于平方根函数只能对非负数进行计算,因此会发生域错误。我们使用if语句检查errno的值,并根据不同的错误类型打印出相应的错误消息。如果没有发生错误,则打印出计算结果。

请注意,我们使用了sqrt()函数来计算平方根,并且没有显式地检查其返回值。这是因为sqrt()函数在发生域错误时会返回一个特殊的值NaN(Not a Number),而不是设置errno的值。因此,我们必须使用errno来检测域错误。

输出结果:

cpp 复制代码
sqrt(-1.000000) 发生域错误

<float.h>

简介

C 标准库的 float.h 头文件包含了一组与浮点值相关的依赖于平台的常量。浮点数是一种用于表示实数的数值类型,它由符号位、基数、指数和精度组成。C 标准库的 <float.h> 头文件定义了与浮点数相关的一些常量,这些常量的值依赖于所运行的平台。

组件 组件描述
S 符号 ( +/- )
b 指数表示的基数,2 表示二进制,10 表示十进制,16 表示十六进制,等等...
e 指数,一个介于最小值 emin 和最大值 emax 之间的整数。
p 精度,基数 b 的有效位数

常见库宏

下面的值是特定实现的,且是通过 #define 指令来定义的,这些值都不得低于下边所给出的值。请注意,所有的 FLT 是指类型 float 的浮点数,DBL 是指类型 double 的浮点数,LDBL 是指类型 long double 的浮点数。

描述
FLT_ROUNDS 定义浮点加法的舍入模式,它可以是下列任何一个值: * -1 - 无法确定 * 0 - 趋向于零 * 1 - 去最近的值 * 2 - 趋向于正无穷 * 3 - 趋向于负无穷
FLT_RADIX 2 这个宏定义了指数表示的基数。基数 2 表示二进制,基数 10 表示十进制,基数 16 表示十六进制。
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG 这些宏定义了 FLT_RADIX 基数中的位数。
FLT_DIG 6 DBL_DIG 10 LDBL_DIG 10 这些宏定义了舍入后不会改变表示的十进制数字的最大值(基数 10)。
FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP 这些宏定义了基数为 FLT_RADIX 时的指数的最小负整数值。
FLT_MIN_10_EXP -37 DBL_MIN_10_EXP -37 LDBL_MIN_10_EXP -37 这些宏定义了基数为 10 时的指数的最小负整数值。
FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP 这些宏定义了基数为 FLT_RADIX 时的指数的最大整数值。
FLT_MAX_10_EXP +37 DBL_MAX_10_EXP +37 LDBL_MAX_10_EXP +37 这些宏定义了基数为 10 时的指数的最大整数值。
FLT_MAX 1E+37 DBL_MAX 1E+37 LDBL_MAX 1E+37 这些宏定义最大的有限浮点值。
FLT_EPSILON 1E-5 DBL_EPSILON 1E-9 LDBL_EPSILON 1E-9 这些宏定义了可表示的最小有效数字。
FLT_MIN 1E-37 DBL_MIN 1E-37 LDBL_MIN 1E-37 这些宏定义了最小的浮点值。

这些常量的值可以在程序中使用,以便在不同的平台上保持浮点数操作的一致性和可移植性。通过使用这些常量,您可以编写与浮点数相关的代码,而不需要关心底层平台的具体细节。

实例

以下是一个使用 <float.h> 头文件中常量的示例代码,它检测浮点数的溢出和下溢情况,并将结果输出到标准输出流:

cpp 复制代码
#include <stdio.h>
#include <float.h>

int main() {
    float f = FLT_MAX;
    double d = DBL_MAX;
    long double ld = LDBL_MAX;

    // 检查浮点数是否溢出或下溢
    if (f > FLT_MAX) {
        printf("float 类型的变量 f 溢出\n");
    } else if (f < FLT_MIN) {
        printf("float 类型的变量 f 下溢\n");
    } else {
        printf("float 类型的变量 f 未溢出也未下溢\n");
    }

    if (d > DBL_MAX) {
        printf("double 类型的变量 d 溢出\n");
    } else if (d < DBL_MIN) {
        printf("double 类型的变量 d 下溢\n");
    } else {
        printf("double 类型的变量 d 未溢出也未下溢\n");
    }

    if (ld > LDBL_MAX) {
        printf("long double 类型的变量 ld 溢出\n");
    } else if (ld < LDBL_MIN) {
        printf("long double 类型的变量 ld 下溢\n");
    } else {
        printf("long double 类型的变量 ld 未溢出也未下溢\n");
    }

    return 0;
}

该程序首先包含了 <stdio.h> 和 <float.h> 头文件。然后,它定义了一个 float 类型的变量 f,一个 double 类型的变量 d 和一个 long double 类型的变量 ld,并将它们分别初始化为它们所能表示的最大值。

接下来,程序使用 <float.h> 头文件中的常量 FLT_MAX、FLT_MIN、DBL_MAX、DBL_MIN、LDBL_MAX 和 LDBL_MIN 来检测浮点数是否溢出或下溢。如果某个变量的值超过了它所能表示的最大值,则认为它溢出;如果它的值小于它所能表示的最小值,则认为它下溢。

最后,程序使用 printf() 函数将结果输出到标准输出流。输出语句使用了格式化字符串,其中 %s 表示一个字符串,而 %f 表示一个浮点数。

让我们编译和运行上面的程序,这将产生下列结果:

cpp 复制代码
float 类型的变量 f 未溢出也未下溢
double 类型的变量 d 未溢出也未下溢
long double 类型的变量 ld 未溢出也未下溢

这个示例程序演示了如何使用 <float.h> 头文件中的常量来检测浮点数的溢出和下溢情况,并将结果输出到标准输出流。

相关推荐
疯一样的码农3 分钟前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
&岁月不待人&25 分钟前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
StayInLove28 分钟前
G1垃圾回收器日志详解
java·开发语言
TeYiToKu30 分钟前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
无尽的大道36 分钟前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
互联网打工人no137 分钟前
每日一题——第一百二十四题
c语言
爱吃生蚝的于勒40 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~43 分钟前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
binishuaio1 小时前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE1 小时前
【Java SE】StringBuffer
java·开发语言