kingofark's Ineffective C/C++:自白1:返回值的运用

LCD、LED、OLED、Mini LED、Micro LED、全阵列LED、QLED、QD-OLED、QNED、AMOLED是什么意思? LCD(液晶显示器,Liquid Crystal Display)定义:LCD 是一种利用液晶材料控制光线通过的显示技术,需依靠背光源(如冷阴极荧光灯 CCFL 或 LED)照亮液晶层以形成图像。技术原理:液晶分子在电场作用下改变排列,控制背光通过的强度和颜色。液晶本身不发光,需外部光源。特点:结构包括背光层、液晶层、彩色滤光片和偏光片。响应时间较慢,黑色表现因背光漏光而偏灰。LED(发光二极管显示,Light Emitting Diode)定义。 阅读详情

Ineffective C/C++ : The Confession of A Novice
《Ineffective C/C++ :一个低手的自白》

by K ][ N G of @ R K

[声明:kingofark并非高手,在论述中所举的例子未必就可取,也未必就是很好的做法。所有例子仅仅是为了说明某些问题,并不具有代表性。kingofark自知才浅,欢迎大家提出批评,指出错误。]

Item 1: Return Values
自白1:返回值的运用


[问题]:试评价如下代码碎片。

/////////////////////////////////////////////////
// ... (在外部定义中)
// 有一组函数属于同一个系统,都以 OK 或者 NG 作为返回值
#define OK   0
#define NG  -1
int AFunction();  //返回OK或者NG

// ... (在某个函数中)
int Rtn;   //存放调用子函数的返回值
Rtn = OK;  //初始化
// ...
Rtn = AFunction();  //调用一个函数
if (Rtn == NG)
{
  //...(这里做一些错误处理)
  return Rtn;  //只要错了就向外退
}
// ...
return Rtn;  //oops! 当前函数返回
/////////////////////////////////////////////////


[kingofark的看法]:

首先需要说明的是,把返回值定成 OK、NG,以及让一组函数具有相同返回方式,这本身并非一个好主意(事实上,笔者认为这个设计很拙劣——但是,你知道,当你是一个软件工人的时候,并非什么东西都是你自己设计的),但这不是本条款所要描述的重点,因此对这些外部的背景条件我们不予讨论。

这个代码碎片至少存在三个问题:

1) 函数返回值的判断方式

/////////////////////////////////////////////////
if (Rtn == NG)
/////////////////////////////////////////////////

"if (Rtn == NG)"意味着:只要返回值不是NG,一律认为是成功。
而"if (Rtn != OK)"意味着:只要返回值不是OK,一律认为是失败。

前者意味着在子函数存在逻辑错误或者发生不可预料的错误时,子函数内部并未陷入代码编写者编写的失败执行路线导致返回NG,而这个子函数调用仍然被认为是成功的——因为此时子函数返回的很可能是OK,甚至是一个垃圾值(如果子函数内部用一个内部变量作为返回值的话),但它不等于NG!

后者附和了函数返回的意义,即只有在子函数内部确实走过了预想的正确执行路线,导致返回OK的情况下才承认调用的正确性,其它所有情况(包括函数失败返回NG以及其它任何不可预料的错误)都认为是失败——这样做的好处是:

    a) 便于调试:只要在函数内部没走到过预想的执行路线,就不返回OK,于是函数调用就被认为是失败的。由此往往能够发现一些函数内部的低级逻辑错误;

    b) 促使函数编写者考虑得尽量周全:如果真的是希望函数具有较高的容错性,请小心安排好返回OK。

2) 初始化的方式

/////////////////////////////////////////////////
Rtn = OK;  //初始化
/////////////////////////////////////////////////

把存放函数返回值的变量初始化为成功的返回值,意味着:

   a) 如果在后面的代码中没用到过这个变量,而又不小心用 "return Rtn;" 返回(从而使编译器也不会警告你这个变量没使用过),那么这个函数就会认为是成功调用的而不管其中发生了什么不可思议的事情,从而使得调试人员很难发现这个函数的问题(调试人员必须很仔细的考察与这个函数相关联的值和该函数产生的效果)。

   b) 编写代码者可能是个乐观主义者。乐观是好事,但并不是说乐观就不会犯错——我们要“严肃活泼”:-)

似乎写 "Rtn = NG;" 更好一些,因为这意味着:在函数中,只要没有将 Rtn 赋值为OK,那么在后面使用 "return Rtn;" 返回时,会返回NG从而引起你的注意,看看是不是什么地方编写错了(比如忘记使用这个变量)。

3) 返回的方式

/////////////////////////////////////////////////
return Rtn;  //oops! 当前函数返回
/////////////////////////////////////////////////

如果函数没有错误系统(即返回值涵盖了一系列设计好的错误码),似乎应该明确以 OK 或者 NG 返回,从而避免因为某种原因而返回垃圾值,比如

Rtn = Fun();  //误用:倒霉!Fun()恰好是一个可能返回多种错误码的函数
return Rtn;   //注意:其实这样返回本身就不好!

或者

//注意:这个写法太诡异,绝对不推荐使用!仅作为举例。
return (Rtn || Flag); //笔误:惨!本来想写 | 来着(其中flag = -1)
 

另外,还有一个需要注意的问题:一定要根据函数的返回值判断函数调用的情况!!

这好像是一句废话,但是就有人这么做:

/////////////////////////////////////////////////
//... (在与前面相同的系统中)
int myfun()
{
  if (...)
  {
    return 1; //一种返回情况
  }
  //...
  return 0;  //另一种返回情况
  //...
}

//...(在另外一个地方的代码中)
Rtn = myfun();
if (Rtn != OK)  //甚或是 if (Rtn == NG)
{
  //...
}
/////////////////////////////////////////////////

是的,一般来说,我们会把诸如OK这样的东西定义为0,但如果万一不是呢?如果后来系统改版,另一个高手决定OK应该等于100呢?

上面的代码中,或许myfun()的编写者仅仅只是忘记了在注释和文档中明确说明“0与该系统中的OK对应;-1与该系统中的NG对应”并且把 "return -1;" 误写为 "return 1;",但是,请铭记:永远只使用函数明确说明的返回值进行返回值判断,无论这个值是否“(应该)实际上与某个外部量相对应”。

只要你坚持使用函数明确说明的返回值进行返回值判断,那么无论是该函数的编写者忘记了说明,还是什么其它琐事,你的做法都是对的。如果你一看,心里想,哦,应该是编写者忘了说明,“本来应该”是使用OK/NG的,所以你就这样做了,那么当OK很不幸的被重新定义为100而该函数又没有做任何更改时,写错代码的就是你。

[kingofark的收获]:

1) 宁可错杀一千,不可放过一个。

2) 只写对的,不玩鬼的。

3) 理想与现实的差距在于:理想中的错误是你想得到的,而现实中的错误有些是你想不到的。

4) 当你调程序调不通的时候,请把你自己认为最不可能出错的地方罗列出来,然后逐个仔细检查。

双有源桥变换器(DAB)TPS控制:从理论建模到Simulink/PSIM仿真实践 本文深入探讨了双有源桥变换器(DAB)的三重移相(TPS)控制技术,从理论建模到仿真实现。文章详细分析了TPS相比SPS和DPS的优势,阐述了其12种工况的划分逻辑与电流应力最优调制策略,并提供了在Simulink和PSIM平台搭建仿真模型的详细步骤与实战经验,帮助工程师掌握这一高效控制方法。 阅读详情

相关推荐

自动驾驶仿真(六)—— SIL软件在环仿真测试

自动驾驶仿真六—— SIL软件在环仿真测试1. 在环仿真测试2. SIL软件在环仿真测试2.1 模型配置参数2.2 S function生成实现2.3 结果对比3. 参考学习的书目教材 博主前面的博文已经简要介绍了Carsim、Prescan 与 Simulink 在 “V”型开发流程的一些应用,现今成熟的汽车控制系统软件都是以(Model Based Design,MBD)来开发,它以图形化的方式表达复杂的逻辑、代码可读性、可移植性、开发调试便利程度都大大增强,同时利用成熟的代码生成工具链,也避免了手工代

zhudj08的博客 8655

测试结果OK、NG、NT、POK的意思

OK:pass,测试通过 NG:not good/not go/fail,不通过 NT:not test,未测试 POK:部分通过

Alex的博客 1万+

告别手动烧录!给STM32H750外挂Flash制作Keil专用下载算法(保姆级避坑指南)

本文详细介绍了为STM32H750外挂Flash开发Keil专用下载算法的全过程,从原理到实战操作,特别针对QSPI Flash的配置和优化提供了保姆级避坑指南。通过定制下载算法,开发者可以告别手动烧录,实现一键下载到外部Flash,大幅提升开发效率。

weixin_42567497的博客 251

Ineffective C++(1):STL容器不仅仅可以保存指针

前言        在公司这两年没少带新人,有刚毕业的,也有工作了两三年的。除了要把公司项目的一些知识告诉他们,通常了需要review一下他们的代码。发现很多人在C++的基本概念上存在错误或者偏差,或者某种习惯用法有瑕疵。这些问题千奇百怪,往往令人哭笑不得。一直想把他们记录下来,于是有了此系列。此系列标题取为Ineffective C++绝对没有想与大师比肩的意思,纯粹是为了搞笑。:)ST

燕良@游戏开发 2913

OpenIddict实战:5步搞定.NET Core应用的OIDC单点登录集成

本文详细介绍了如何使用OpenIddict在.NET Core应用中快速实现OIDC单点登录集成。通过五个关键步骤,包括环境准备、数据库集成、客户端注册、令牌配置和多应用SSO集成,帮助开发者高效构建安全的企业级单点登录解决方案。

lambda的博客 728

9 HAL库驱动框架简述(STM32HAL库)

HAL库外设的使用步骤总结如下:1、定义并填充xxx外设句柄结构体。2、如果遵循HAL库规范,通过HAL_xxx_MspInit()函数,实现外设底层资源的初始化,包括但不限于GPIO、时钟、DMA、中断等资源的初始化。3、调用HAL库的对应外设初始化函数,形如:HAL_xxx_Init()。4、初始化完成,开始使用外设。5、使用方法具体查看对应外设的HAL库驱动包中的说明:补充:HAL库使用主线外设初始化外设使用。

qq_25218501的博客 1983

kingofark's Ineffective C/C++:自白1:返回值的运用 (转)

kingofark's Ineffective C/C++:自白1:返回值的运用 (转)[@more@]Ineffective C/C++ : The Confession of A Novice《Ineffective C/C...

csd3176的博客 141

本地AI语音生成与配音工作台Pandrator:从TTS到RVC的完整实践指南

语音合成(TTS)技术通过深度学习模型将文本转换为自然语音,其核心原理涉及声学建模与波形生成。这项技术不仅提升了人机交互体验,更在内容创作领域展现出巨大价值,广泛应用于有声书制作、视频配音、虚拟助手等场景。本文聚焦于一个集成了XTTS-v2、RVC等先进模型的本地化AI语音工作台——Pandrator,它通过模块化架构将语音合成、声音克隆、音频转录与翻译等流程无缝整合,为用户提供了一个图形化、可定制的完整解决方案。文章深入解析了其基于TTS与RVC(Retrieval-based Voice Convers

weixin_42676876的博客 340

kingofark's Ineffective C/C++:自白2:有符号、无符号还有位运算,我的天!

Ineffective C/C++ : The Confession of A Novice《Ineffective C/C++ :一个低手的自白》by K ][ N G of @ R K[声明:kingofark并非高手,在论述中所举的例子未必就可取,也未必就是很好的做法。所有例子仅仅是为了说明某些问题,并不具有代表性。kingofark自知才浅,欢迎大家提出批评,指出错误。]Ite

方舟 K ][ N G of A R K 1893

基于Simulink的电力电子系统电磁兼容性(EMC)仿真

在电力电子系统中,由于高频开关器件的存在,会产生大量的电磁干扰(EMI),这对系统的稳定性和可靠性提出了挑战。Simulink 提供了一个强大的仿真环境,可以用来设计、分析和验证电力电子系统的电磁兼容性。本教程将详细介绍如何使用 Simulink 进行电力电子系统的电磁兼容性仿真。通过本教程,我们详细介绍了如何使用 Simulink 进行电力电子系统的电磁兼容性仿真。为了模拟电力电子系统中的电磁干扰(EMI),我们需要添加噪声源模块。为了更好地分析系统的电磁兼容性特性,可以在模型中添加频谱分析工具。

amy_mhd的博客 1126

lp–mspm0g3507开发板进入低功耗模式怎么退出?烧程序烧着烧着就进来了,跳线帽没动过,且报错:Texas Instruments Debugger Error: DAP Co...如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 1570

走近所罗门 Part 1 邮件中的所罗门

走近所罗门 Part 1:邮件中的所罗门本文的由来:随着Mark E. Russinovich, David A. Solomon原著,潘爱民老师译《深入解析Windows操作系统,第4版》(Windows Internals 4th Edition)的出版,得以有机会与该书的原作者之一,世界顶尖的Windows操作系统内核专家David A. Solomon见面和交流。心有感触,在此记之。最初与

方舟 K ][ N G of A R K 7241

零基础入门篇③ PyCharm使用指南(个性化设置、开发必备插件、常用快捷键)

Python从入门到精通👉零基础入门篇③

hacker707的博客 4376

《交互设计沉思录》译序

图书链接:http://book.douban.com/subject/19934344/亚马逊:http://www.amazon.cn/UI设计丛书•交互设计沉思录-顶尖设计专家Jon-Kolko的经验与心得-科尔科/dp/B009A7DAXI/当当网:http://product.dangdang.com/product.aspx?product_id=22873892【名家力荐】“Jon在

方舟 K ][ N G of A R K 6450

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

走近所罗门 Part 2:初见所罗门

 走近所罗门 Part 2:初见所罗门本文的由来:随着Mark E. Russinovich, David A. Solomon原著,潘爱民老师译《深入解析Windows操作系统,第4版》(Windows Internals 4th Edition)的出版,得以有机会与该书的原作者之一,世界顶尖的Windows操作系统内核专家David A. Solomon见面和交流。心有感触,在此记之。2007

方舟 K ][ N G of A R K 6435

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

上一篇: kingofark's Ineffective C/C++:自白2:有符号、无符号还有位运算,我的天!
下一篇: kingofark's Ineffective C/C++:低手自序
kingofark
博客等级 码龄26年 330粉丝 134原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值