C语言标准库<math.h>和<setjmp.h>的实现

 更新时间:2023年11月22日 15:01:10   作者:世俗ˊ  
本文主要介绍了C语言标准库<math.h>和<setjmp.h>的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

<math.h>

简介

<math.h> 是 C 标准库中的一个头文件,主要提供了数学运算相关的函数和宏定义。它允许您在 C 程序中执行各种常见的数学计算,如三角函数、对数、指数、幂运算等。

库宏

下面是这个库中定义的唯一的一个宏:

HUGE_VAL 是 <math.h> 头文件中定义的一个宏,用于表示一个特定的很大的值。当数学函数的结果无法表示为浮点数时,可以使用 HUGE_VAL 来表示超出范围的结果。

具体来说,如果函数的结果幅度太大以至于无法表示,则函数会将 errno 设置为 ERANGE,表示范围错误,并返回 HUGE_VAL 或 -HUGE_VAL。这允许您判断函数是否返回了一个超出可表示范围的值。

另一方面,如果函数的结果幅度太小,则可能会返回零值。在这种情况下,errno 可能被设置为 ERANGE,也可能不被设置为 ERANGE。因此,在使用数学函数并处理其返回值时,需要注意检查 errno 的值是否指示了错误。

总之,HUGE_VAL 宏对于处理超出可表示范围的数值是非常有用的,可以帮助进行错误处理和边界检查。

库函数

下面列出了头文件 math.h 中定义的函数:

double acos(double x):返回以弧度表示的 x 的反余弦。
double asin(double x):返回以弧度表示的 x 的反正弦。
double atan(double x):返回以弧度表示的 x 的反正切。
double atan2(double y, double x):返回以弧度表示的 y/x 的反正切。y 和 x 的值的符号决定了正确的象限。
double cos(double x):返回弧度角 x 的余弦。
double cosh(double x):返回 x 的双曲余弦。
double sin(double x):返回弧度角 x 的正弦。
double sinh(double x):返回 x 的双曲正弦。
double tanh(double x):返回 x 的双曲正切。
double exp(double x):返回 e 的 x 次幂的值。
double frexp(double x, int *exponent):把浮点数 x 分解成尾数和指数。返回值是尾数,并将指数存入 exponent 中。所得的值是 x = mantissa * 2 ^ exponent。
double ldexp(double x, int exponent):返回 x 乘以 2 的 exponent 次幂。
double log(double x):返回 x 的自然对数(基数为 e 的对数)。
double log10(double x):返回 x 的常用对数(基数为 10 的对数)。
double modf(double x, double *integer):返回值为小数部分(小数点后的部分),并设置 integer 为整数部分。
double pow(double x, double y):返回 x 的 y 次幂。
double sqrt(double x):返回 x 的平方根。
double ceil(double x):返回大于或等于 x 的最小的整数值。
double fabs(double x):返回 x 的绝对值。
double floor(double x):返回小于或等于 x 的最大的整数值。
double fmod(double x, double y):返回 x 除以 y 的余数。

实例

以下是一个简单的代码示例,展示了如何使用 <math.h> 头文件中的一些函数来进行数学计算:

#include <stdio.h>
#include <math.h>  // 引入 math.h 头文件
 
int main() {
    double x = 1.5;
    double y = 2.7;
 
    // 计算 x 的双曲正弦值和反正切值
    double sinh_x = sinh(x);
    double atan_x = atan(x);
 
    // 计算 x 的立方根和以 2 为底的对数
    double cbrt_x = cbrt(x);
    double log2_x = log2(x);
 
    // 计算 y 的向下取整值和 x 与 y 的余数
    double floor_y = floor(y);
    double fmod_xy = fmod(x, y);
 
    // 打印计算结果
    printf("sinh(%.2f) = %.2f\n", x, sinh_x);
    printf("atan(%.2f) = %.2f\n", x, atan_x);
    printf("cbrt(%.2f) = %.2f\n", x, cbrt_x);
    printf("log2(%.2f) = %.2f\n", x, log2_x);
    printf("floor(%.2f) = %.2f\n", y, floor_y);
    printf("%.2f %% %.2f = %.2f\n", x, y, fmod_xy);
 
    return 0;
}

需要注意的是,这些函数在使用的时候需要特别小心,因为它们有可能会产生一些异常情况(例如超出计算机数值范围等)。

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

sinh(1.50) = 2.13
atan(1.50) = 0.98
cbrt(1.50) = 1.14
log2(1.50) = 0.58
floor(2.70) = 2.00
1.50 % 2.70 = 1.50

<setjmp.h>

简介

<setjmp.h> 是 C 标准库中的一个头文件,提供了一种非局部跳转的机制,允许程序在一个函数中设置一个跳转点,并在另一个函数中跳转到该点。

库变量

<setjmp.h> 头文件并没有定义任何变量。只定义了 jmp_buf 类型作为 setjmp 和 longjmp 函数的参数类型。jmp_buf 是一个用于存储跳转点信息的数组类型,具体的实现细节是未定义的,通常被编译器实现为一个足够大的数组。

请注意,虽然 <setjmp.h> 中没有定义变量,但您可以在程序中创建自己的 jmp_buf 变量,并将其传递给 setjmp 和 longjmp 函数来实现非局部跳转的功能。

库函数

<setjmp.h> 头文件中定义了两个函数:setjmp 和 longjmp,用于实现非局部跳转和异常处理机制。

1、int setjmp(jmp_buf env) 函数

该函数将调用它的地方的当前执行状态保存在 env 中,并返回 0。如果 setjmp 是由 longjmp 跳转回来的,则返回一个非零值。

2、void longjmp(jmp_buf env, int val) 函数

该函数根据传递的 env 参数,恢复相应的执行状态,并跳转到相应的位置。val 参数是返回到 setjmp 的返回值。
这两个函数一起提供了非常有用的异常处理机制,通常用于处理错误或异常情况,以及在程序中实现类似于异常处理的功能。

使用 <setjmp.h> 头文件时,需要注意以下几点:

  • setjmp 和 longjmp 必须在同一个函数调用链中使用,而且 setjmp 必须在 longjmp 之前调用。
  • jmp_buf 类型是一个数组类型,它存储了用于保存执行状态的信息。然而,具体的实现细节是未定义的,因此不能直接访问 jmp_buf 的成员。
  • 使用 setjmp 和 longjmp 时应谨慎,因为它们会导致程序的控制流程变得复杂,并且可能使代码更难理解和维护。

需要注意的是,<setjmp.h> 头文件提供了一种非常底层的编程机制,一般情况下并不推荐频繁使用。

实例

#include <stdio.h>
#include <setjmp.h>
 
jmp_buf exception_env; // 用于保存执行状态的全局变量
 
void handle_exception() {
    printf("捕获到异常,进行异常处理\n");
}
 
void do_something_dangerous(int input) {
    if (input < 0) {
        longjmp(exception_env, 1); // 跳转到异常处理代码
    } else {
        printf("正常处理输入:%d\n", input);
    }
}
 
int main() {
    if (setjmp(exception_env) == 0) { // 设置异常跳转点
        // 正常情况
        do_something_dangerous(10);
        do_something_dangerous(-5); // 这里会触发异常
        do_something_dangerous(20); // 这里不会执行
    } else {
        // 异常处理
        handle_exception();
    }
 
    return 0;
}

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

正常处理输入:10
捕获到异常,进行异常处理

这个示例中定义了一个全局的 jmp_buf 类型的变量 exception_env,用于保存执行状态。在 main 函数中,通过 setjmp 设置了一个异常跳转点,并在 do_something_dangerous 函数中对输入进行判断,如果输入小于 0,则调用 longjmp 跳转到异常处理代码。在跳转回来后,程序可以进行相应的异常处理。

需要注意的是,setjmp 和 longjmp 是比较底层的机制,使用时需要特别小心,因为它们会使程序的控制流程变得复杂,也容易引入难以调试的错误。

到此这篇关于C语言标准库<math.h>和<setjmp.h>的实现的文章就介绍到这了,更多相关C语言 <math.h>和<setjmp.h>内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈Linux环境下并发编程中C语言fork()函数的使用

    浅谈Linux环境下并发编程中C语言fork()函数的使用

    fork函数在Linux中可以创建子进程即一个新的进程,这里我们根据实例来浅谈Linux环境下并发编程中C语言fork()函数的使用,需要的朋友可以参考下
    2016-06-06
  • C++实现LeetCode(137.单独的数字之二)

    C++实现LeetCode(137.单独的数字之二)

    这篇文章主要介绍了C++实现LeetCode(137.单独的数字之二),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • OpenMP task construct 实现原理及源码示例解析

    OpenMP task construct 实现原理及源码示例解析

    这篇文章主要为大家介绍了OpenMP task construct 实现原理及源码示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • C语言实现学生信息管理系统(文件版)

    C语言实现学生信息管理系统(文件版)

    这篇文章主要为大家详细介绍了C语言实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • Qt两种定时器使用实现方式

    Qt两种定时器使用实现方式

    这篇文章主要给大家介绍了关于Qt两种定时器使用实现方式的相关资料,Qt中的定时器类是QTimer,QTimer不是一个可见的界面组件,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • C++基础知识之运算符重载详解

    C++基础知识之运算符重载详解

    这篇文章主要为大家详细介绍了C++基础知识之运算符重载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++利用libcurl获取下载文件名称及大小

    C++利用libcurl获取下载文件名称及大小

    这篇文章主要为大家详细介绍了C++如何利用libcurl获取下载文件名称及大小的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-03-03
  • 深入浅析C/C++语言结构体指针的使用注意事项

    深入浅析C/C++语言结构体指针的使用注意事项

    这篇文章主要介绍了C/C++语言结构体指针的使用,大家都知道指针在32位系统占用4Byte,在64位系统占用8Byte,下面看下c语言代码例子
    2021-12-12
  • OpenCV实现图像连通域

    OpenCV实现图像连通域

    这篇文章主要为大家详细介绍了OpenCV实现图像连通域,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C++取得本机IP的方法

    C++取得本机IP的方法

    这篇文章主要介绍了C++取得本机IP的方法,代码简单功能实用,具有不错的借鉴参考价值,需要的朋友可以参考下
    2014-10-10

最新评论