調用 asin、log、pow 等數學函數時,若參數超出定義域會產生運行時錯誤。手工檢查參數(特別是 pow(x,y) 的複雜定義域)繁瑣且易出錯。
原型:int _matherr(struct _exception *except);
編譯器會在數學庫函數檢測到錯誤時自動調用該函數,無需顯式調用。
| 成員 | 含義 |
|---|---|
| int type | 異常類型 |
| char *name | 出錯函數名 |
| double arg1, arg2 | 函數參數 |
| double retval | 函數返回值(可修改) |
_DOMAIN:定義域錯誤_SING:奇異點錯誤_OVERFLOW:溢出_PLOSS:精度部分遺失_TLOSS:精度完全遺失_UNDERFLOW:下溢errnoerrno 不變,可通過修改 retval 返回自定義值
#include <math.h> #include <stdio.h>
int _matherr(struct _exception *except) {
static char* errStr[] = {"_DOMAIN","_SING","_OVERFLOW","_PLOSS","_TLOSS","_UNDERFLOW"};
printf("Error function: %s\n", except->name);
printf("Args: %g, %g\n", except->arg1, except->arg2);
printf("Type: %s\n", errStr[except->type]);
printf("Default retval: %g\n", except->retval);
except->retval = 1234; // 自定義返回值
printf("New retval: %g\n", except->retval);
return 1; // 抑制默認錯誤輸出
}
void main() {
double x = -1.23, y = -1.1, z;
z = pow(x, y); // 觸發 _SING
printf("%g\n", z); // 輸出 1234
}
輸出:
Error function: pow Args: -1.23, -1.1 Type: _SING Default retval: -1.#IND New retval: 1234 1234
int _matherr(struct _exception *except) {
if (except->type == _DOMAIN) {
if (strcmp(except->name, "log") == 0) {
except->retval = log(-except->arg1);
printf("Special: using absolute value: %s: _DOMAIN error\n", except->name);
return 1;
}
if (strcmp(except->name, "log10") == 0) {
except->retval = log10(-except->arg1);
printf("Special: using absolute value: %s: _DOMAIN error\n", except->name);
return 1;
}
}
printf("Normal: ");
return 0; // 其他錯誤走默認處理
}
_matherr 提供集中式數學錯誤處理機制,適用於參數來源不可控(用戶輸入、中間計算結果)的場景,避免大量分散的 if 判斷。注意:僅對 Microsoft C 運行時庫的數學函數有效。