从 ISO C99 开始,我们有一些宏(或常量)可以帮助理解一些数学错误(参见
以文件“me.c”为例
#include <math.h>
#include <stdio.h>
#include <errno.h>
int main(void)
{
if (math_errhandling & MATH_ERRNO)
{
if (errno == EDOM)
{
fprintf(stderr, "Domain error!\n");
}
}
return 0;
}
我用MinGW64(GCC 14.2.0)编译如下
gcc -std=c11 -Wall -Wextra -O2 -lm me.c -o me.exe
me.c: In function 'main':
me.c:7:9: error: 'math_errhandling' undeclared (first use in this function)
7 | if (math_errhandling & MATH_ERRNO)
| ^~~~~~~~~~~~~~~~
me.c:7:9: note: each undeclared identifier is reported only once for each function it appears in
me.c:7:28: error: 'MATH_ERRNO' undeclared (first use in this function)
7 | if (math_errhandling & MATH_ERRNO)
| ^~~~~~~~~~
使用 Clang (19.1.3) 编译的相同代码没有显示错误
clang -std=c11 -Wall -Wextra -O2 me.c -o me.exe
我在 GCC 调用中遗漏了什么吗?
我将举例说明[SO]:在 C(Windows 10 操作系统)中未声明的 math_errhandling(@CristiFati 的答案)。
输出:
Ubuntu 20 pc064:
[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q075000209]> ~/sopr.sh ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [064bit prompt]> ls main00.c main_win_pc064_vs19.exe [064bit prompt]> [064bit prompt]> # ---------- GCC ---------- [064bit prompt]> gcc --version | grep gcc gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0 [064bit prompt]> gcc -fPIC -o main_linux_pc064_gcc main00.c -lm [064bit prompt]> [064bit prompt]> ./main_linux_pc064_gcc MATH_ERRNO: 0x00000001 MATH_ERREXCEPT: 0x00000002 math_errhandling: 0x00000003 EDOM: 0x00000021 Done. [064bit prompt]> [064bit prompt]> # ---------- CLang ---------- [064bit prompt]> clang --version | grep version clang version 10.0.0-4ubuntu1 [064bit prompt]> clang -fPIC -o main_linux_pc064_clang main00.c -lm [064bit prompt]> [064bit prompt]> ./main_linux_pc064_clang MATH_ERRNO: 0x00000001 MATH_ERREXCEPT: 0x00000002 math_errhandling: 0x00000003 EDOM: 0x00000021 Done. [064bit prompt]> [064bit prompt]> # ---------- MinGW64 GCC ---------- [064bit prompt]> x86_64-w64-mingw32-gcc --version | grep gcc x86_64-w64-mingw32-gcc (GCC) 9.3-win32 20200320 [064bit prompt]> x86_64-w64-mingw32-gcc -fPIC -o main_linux_pc064_mgw64gcc main00.c -lm main00.c: In function ‘main’: main00.c:8:36: error: ‘MATH_ERRNO’ undeclared (first use in this function) 8 | printf("MATH_ERRNO: 0x%08X\n", MATH_ERRNO); | ^~~~~~~~~~ main00.c:8:36: note: each undeclared identifier is reported only once for each function it appears in main00.c:9:40: error: ‘MATH_ERREXCEPT’ undeclared (first use in this function) 9 | printf("MATH_ERREXCEPT: 0x%08X\n", MATH_ERREXCEPT); | ^~~~~~~~~~~~~~ main00.c:10:42: error: ‘math_errhandling’ undeclared (first use in this function) 10 | printf("math_errhandling: 0x%08X\n", math_errhandling); | ^~~~~~~~~~~~~~~~ [064bit prompt]>
Cygwin pc064:
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackExchange/StackOverflow/q075000209]> ~/sopr.sh ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [064bit prompt]> ls main00.c main_linux_pc064_clang main_linux_pc064_gcc main_win_pc064_vs19.exe [064bit prompt]> [064bit prompt]> # ---------- GCC ---------- [064bit prompt]> gcc --version | grep gcc gcc (GCC) 12.4.0 [064bit prompt]> gcc -fPIC -o main_cyg_pc064_gcc main00.c -lm [064bit prompt]> [064bit prompt]> ./main_cyg_pc064_gcc MATH_ERRNO: 0x00000001 MATH_ERREXCEPT: 0x00000002 math_errhandling: 0x00000003 EDOM: 0x00000021 Done. [064bit prompt]> [064bit prompt]> # ---------- MinGW64 GCC ---------- [064bit prompt]> x86_64-w64-mingw32-gcc --version | grep gcc x86_64-w64-mingw32-gcc (GCC) 12.4.0 [064bit prompt]> x86_64-w64-mingw32-gcc -fPIC -o main_cyg_pc064_mgw64gcc main00.c -lm main00.c: In function ‘main’: main00.c:8:36: error: ‘MATH_ERRNO’ undeclared (first use in this function) 8 | printf("MATH_ERRNO: 0x%08X\n", MATH_ERRNO); | ^~~~~~~~~~ main00.c:8:36: note: each undeclared identifier is reported only once for each function it appears in main00.c:9:40: error: ‘MATH_ERREXCEPT’ undeclared (first use in this function) 9 | printf("MATH_ERREXCEPT: 0x%08X\n", MATH_ERREXCEPT); | ^~~~~~~~~~~~~~ main00.c:10:42: error: ‘math_errhandling’ undeclared (first use in this function) 10 | printf("math_errhandling: 0x%08X\n", math_errhandling); | ^~~~~~~~~~~~~~~~ [064bit prompt]> [064bit prompt]> # ---------- MinGW32 GCC ---------- [064bit prompt]> i686-w64-mingw32-gcc --version | grep gcc i686-w64-mingw32-gcc (GCC) 12.4.0 [064bit prompt]> i686-w64-mingw32-gcc -fPIC -o main_cyg_pc064_mgw32gcc main00.c -lm main00.c: In function ‘main’: main00.c:8:36: error: ‘MATH_ERRNO’ undeclared (first use in this function) 8 | printf("MATH_ERRNO: 0x%08X\n", MATH_ERRNO); | ^~~~~~~~~~ main00.c:8:36: note: each undeclared identifier is reported only once for each function it appears in main00.c:9:40: error: ‘MATH_ERREXCEPT’ undeclared (first use in this function) 9 | printf("MATH_ERREXCEPT: 0x%08X\n", MATH_ERREXCEPT); | ^~~~~~~~~~~~~~ main00.c:10:42: error: ‘math_errhandling’ undeclared (first use in this function) 10 | printf("math_errhandling: 0x%08X\n", math_errhandling); | ^~~~~~~~~~~~~~~~ [064bit prompt]>
Win(与其他答案中相同的Cmd窗口):
[prompt]> dir /b main00.c main_cyg_pc064_gcc.exe main_linux_pc064_clang main_linux_pc064_gcc main_win_pc064_vs19.exe [prompt]> gcc 'gcc' is not recognized as an internal or external command, operable program or batch file. [prompt]> [prompt]> :: ---------- MinGW64 GCC ---------- [prompt]> set PATH=%PATH%;f:\Install\Qt\Qt\Tools\mingw730_64\bin [prompt]> gcc --version | findstr gcc gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0 [prompt]> gcc -fPIC -o main_win_pc064_mgw64gcc main00.c -lm main00.c: In function 'main': main00.c:8:36: error: 'MATH_ERRNO' undeclared (first use in this function); did you mean '_INC_ERRNO'? printf("MATH_ERRNO: 0x%08X\n", MATH_ERRNO); ^~~~~~~~~~ _INC_ERRNO main00.c:8:36: note: each undeclared identifier is reported only once for each function it appears in main00.c:9:40: error: 'MATH_ERREXCEPT' undeclared (first use in this function); did you mean 'MATH_ERRNO'? printf("MATH_ERREXCEPT: 0x%08X\n", MATH_ERREXCEPT); ^~~~~~~~~~~~~~ MATH_ERRNO main00.c:10:42: error: 'math_errhandling' undeclared (first use in this function) printf("math_errhandling: 0x%08X\n", math_errhandling); ^~~~~~~~~~~~~~~~ [prompt]>
不同的 OS、风格、编译器、版本,行为似乎一致:MinGW64 GCC 的 math.h 没有定义宏。
在网上查了一下,发现这些文章提到了同样的错误:
[SourceForge]:Mingw-64 预防和检测数学函数中的域和范围错误其中指出:
我找到了解决方案。事实证明,您必须使用 -fsignaling-nans 标志进行编译。
我尝试过,但没有成功。也许该标志是用于构建 MinGW 本身?
还进行了一些 math.h 比较,看来宏没有在属于 MinGW 的宏中定义。
看起来这是一个死胡同。