在C中,是否有一种模式可以不再检查调用其他函数的函数中的错误?
例如,如果函数foo()依次调用a(),b()和c(),则必须在继续之前检查每个函数的返回值。 如果a(),b()或c()也调用其他函数,这些函数也可能调用其他函数,这会留下一长串错误检查,可能出现相同的错误……
int16_t a(x_t x) {return DO_SOME_WORK(x);} int16_t b(y_t y) {return DO_OTHER_WORK(y);} int16_t c(z_t z) {return DO_MORE_WORk(z);} foo (x_t x, y_t y, z_t z) { int16_t err = 0; // I can handle errors returned by either: err = a(x)); if (err) return err; err = b(y); if (err) return err; err = c(z); return err; // Or err = a(x); if (!err) err = b(y); if (!err) err = c(z); return err; }
我更喜欢第二种方法,因为有一个明确的单一退出点,但另一种方法本地化处理和任何一种方法引入了大量的ifs,并且使用大型程序,这是很多额外的代码,特别是在除了调用其他函数之外什么都不做的函数中例如,函数并传递它们之间的输出。 谢谢
在这种情况下,您可以利用&&
的短路评估,其中当左侧操作数为false
,不评估右侧操作数。
如果您可能希望在对a()
, b()
或c()
调用之间执行其他处理,则以下内容允许:
bool foo (x_t x, y_t y, z_t z) { bool err = a( x ); err = err && b( y ) ; err = err && c( z ) ; return err; }
而如果函数只由调用a()
, b()
或c()
,那么你可以使用更简洁:
bool foo (x_t x, y_t y, z_t z) { return a( x ) && b( y ) && c( z ) ; }
[补充回应评论]
解决@kkrambo关于函数返回的任何数值没有传播给调用者的观点可以解决,但作为解决方案的吸引力越来越小:
int16_t foo (x_t x, y_t y, z_t z) { int16_t ret ; bool err = (ret = a( x )); err = err && (ret = b( y )) ; err = err && (ret = c( z )) ; return ret ; }
要么
int16_t foo (x_t x, y_t y, z_t z) { uint16_t ret ; (ret = a( x )) && (ret = b( y )) && (ret = c( z )) ; return ret ; }
你甚至可以做到可怕的增加:
int16_t foo (x_t x, y_t y, z_t z) { int16_t err ; if( (err = a(x)) ) {} else if( (err = b(y)) ) {} else if( (err = c(z)) ) {} return err ; }
简化以下内容,其中err
是布尔值:
bool foo (x_t x, y_t y, z_t z) { bool err = true ; if( a(x) ) {} else if( b(y) ) {} else if( c(z) ) {} else { err = false } return err ; }
如果函数的每个函数调用都需要错误检查,那么每次调用该函数时都应检查错误。 原因是即使它是相同的函数,输入也是不同的,并且全局(和静态局部)变量是不同的,从而改变结果。 这意味着如果你想检查错误,你实际上并没有浪费计算工作。
编辑:我不知道这是否明智但你可以使用宏来清理语法
err = a(x); if(err) return err;
它看起来像
#define error_check(f, e) e = f; if(e) return e;
所以在你的代码中你可以写
error_check(a(x),err)
我没有使用宏,但这应该工作。
由于目标是返回错误代码而不是简单的布尔值,因此OP提供的2种方法至少是合理的,如果不是优选的话。 像if (a(x) || b(x)) return true
短路代码无法保持从a()
和b()
派生的err
值。
它归结为风格。
如果代码简单由几行组成,任何方法都足够了。 但是考虑到a(x)
, b(x)
和c(x)
之间可能存在重要的代码,建议不要使用样式2,因为它在许多代码行之间分离流。 我喜欢风格3超过1,因为它有点简洁,但1和3之间的差异很小。
为了应对样式#2在一个位置收集错误返回的能力,考虑一个更高级别的函数包装器,它可以明确地确保所有序言和结尾活动的发生。
最佳选择:遵循团队风格指南,否则最适合您维护 ,而不是写作。
int16_t foo (x_t x, y_t y, z_t z) { // added matching return type int16_t err = 0; // OP style 1 err = a(x)); if (err) return err; err = b(y); if (err) return err; err = c(z); return err; // OP style 2 err = a(x); if (!err) err = b(y); if (!err) err = c(z); return err; // style 3 // via enum or define, create an OK symbol if ((err = a(x)) != OK) return err; if ((err = b(x)) != OK) return err; if ((err = c(x)) != OK) return err; // }
以上就是c/c++开发分享模式,以防止不断检查错误?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/541801.html