谁帮我把华为y7 prime3000 c百度一下并贴出来

你好我是华为手机的使用者,我的手机是 华为是y3000,我想把我的手机root了。前几天我在网上看到需要弄_百度知道
你好我是华为手机的使用者,我的手机是 华为是y3000,我想把我的手机root了。前几天我在网上看到需要弄
解锁码,现在我把解锁码弄到了,不知道下一步该怎么做
,麻烦专家给我细解,谢谢!
我有更好的答案
你手机过保修期了吗?如果没过建议不要ROOT。那样就没保修了。假如坏了就要自己掏钱维修了。
采纳率:66%
你需要以root获取系统最高权限,可以通过第三方软件,如钛备份卸载系统程序.0ROOT将恢复出厂设置。 不知道要问,一些手机4。 ROOT请访问相应的教程卸载系统程序的风险,可能会导致系统错误,程序不能使用,相应的系统崩溃等问题,被视为慎用。 根的重要信息备份一次发言前不要刷机
其实就是安卓ROOT
为您推荐:
其他类似问题
华为手机的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。信息与通信解决方案供应商。关注话题分享阅读全文15K1,107 条评论分享收藏感谢阅读全文13K1,403 条评论分享收藏阅读全文12K2,059 条评论分享收藏感谢阅读全文9.7K1,174 条评论分享收藏阅读全文8.9K839 条评论分享收藏感谢76,174cnBeta.COM - 中文业界资讯站
微软 Surface Book 2新品中国上市:12388元起亚马逊在西雅图开设热带雨林圆顶办公室
据今日俄罗斯2月11日报道,一架由萨拉托夫航空公司运营的“安东诺夫-148”飞机从莫斯科起飞后失踪,飞机上有65名乘客和6名工作人员。俄罗斯卫星通讯社援引消息人士的话称,从空中坠毁的飞机已在莫斯科郊外的拉缅斯科地区找到。
发布于 22:25&&|&&2126次阅读&&|&&0个意见
Utrankar在读医学院的第二年,在田纳西州的范德比尔特大学医疗中心工作,当时一位主管要求他获得一份新病人的病历。当时22岁的Utrankar需要从一个较小的社区医院获得病历,该医院的病人此前曾接受过治疗。这包括填写一份标有病人签名的标准记录申请表,并传真过去。唯一的问题是,Utrankar不知道如何使用传真机。
发布于 22:22&&|&&2223次阅读&&|&&0个意见
共青城赛龙通信科技有限公司(下称“共青赛龙”)、创始人代小权逃税案迎来二审宣判,代小权被当庭释放。2月11日,江西省九江市中级人民法院公开开庭审理上述案件,该院当庭宣判:撤销江西省共青城市人民法院(2017)赣0482刑初2号刑事判决,宣告上诉单位共青赛龙、上诉人代小权无罪。
发布于 21:08&&|&&2208次阅读&&|&&0个意见
一项新的研究发现,气候变化可能不像人们曾经认为的那样不可逆转。英属哥伦比亚大学的研究人员发现,先前对煤炭使用导致的全球变暖的估计可能是不现实的。换句话说,之前对全球变暖程度的估计太过严重,实际上情形并没有坏到那种程度。
发布于 21:06&&|&&1199次阅读&&|&&0个意见
根据伦敦路透社报道,巴克莱银行信用卡部门的一位高管在接受采访时透露,巴克莱很有可能会仿照美国几家大贷款机构的做法:拒绝为用户提供信用卡来购买比特币或者其他加密货币。巴克莱的总经理Paul
Wilmore在Bank Innovation博客上表示:“不允许使用信用卡购买加密货币,这很有可能会在巴克莱变成事实。”
发布于 20:24&&|&&526次阅读&&|&&0个意见
今年,支付宝又启动了一年一度的集五福分红包活动,玩法更多,红包总额也猛增至5亿元。集福卡的方式有三种,分别是支付宝AR扫任一福字或扫身边好友“五福到”手势、在蚂蚁庄园中收取金蛋、参与蚂蚁森林浇水活动,好友之间还可以转增福卡。
发布于 20:24&&|&&5863次阅读&&|&&2个意见
小镇青年,曾经是作家笔下极具符号特征的文学形象,然而如今提起小镇青年,少了些文艺的味道,却多了几分忧思。有记者近日走访部分农村调研发现,在青年人口流失严重的乡镇村落,留下的一些青年严重沉溺于手机游戏和低俗网络文化,精神文化生活贫乏单一。
发布于 19:54&&|&&3554次阅读&&|&&1个意见
乘火车可以“刷脸”进站,坐飞机可以手机空中上网,12306系统新技术维护网络购票“排队秩序”……2018年春运进入高峰期,一系列新技术让出行更便捷、更高效、更公平,回家路上票难买、排队长、吃饭贵等难题正逐步改善。
发布于 19:54&&|&&901次阅读&&|&&0个意见
2月7日,中国消费者协会发布通告,公布对来自多家网购平台的海淘商品“验货”情况。此后,网易考拉、聚美优品等平台相继发布回应,称商品只是来自海外,不是“假货”,一时引发争议。4天过去,对此,中国消费者协会相关负责人对新京报记者表示,所有的信息在7日的报告中已经公布,没有任何改变。
发布于 19:53&&|&&2102次阅读&&|&&0个意见
中国联通(600050)混改方案的最后一块拼图——员工股权激励计划方案出炉。2月11日,中国联通发布关于限制性股票激励计划(草案修订稿)及首期授予方案(草案修订稿)等一系列相关公告。根据公告,中国联通此次股权激励计划首期拟向激励对象授予不超过84788万股的限制性股票,约占当前公司股本总额的2.8%,其中计划预留4485.6万股,占本次授予总量的5.3%,占当前公司股本总额的0.1%。
发布于 19:04&&|&&1452次阅读&&|&&0个意见
近日,俄罗斯的太空行走创下新的纪录,但在国际空间站外的一个重要天线安装却出现朝向失误。太空行走的缘由是更换一个旧的通讯模块,40岁的宇航员Aleksandr Misurkin和45岁的宇航员Anton Shkaplerov不得不冒险在进行太空行走。
发布于 18:49&&|&&1688次阅读&&|&&0个意见
在刚刚结束的马来西亚一项电竞邀请赛上,杭州电竞战队LGD俱乐部女队拿到了冠军。提到女子电竞选手,或许你会想到这样一些词:大长腿、高颜值……甚至是花瓶。但杭州这支女子电竞战队的妹子们,通过自己的故事告诉你更多关于女子电竞选手的“真相”:接触电竞是从小时候玩小霸王游戏机开始,放弃了枯燥的会计工作选择挑战更大的电竞,收入也就是和普通同龄人差不多……
发布于 18:35&&|&&7010次阅读&&|&&2个意见
更多核心成了Intel反击AMD崛起的杀手锏:发烧级一口气推进到18核心,桌面主流i7/i5全部上六核心,i3也都是四核心,而在笔记本上,U系列低压版都普及了四核心。迄今为止,Coffee
Lake八代酷睿家族在笔记本平台上只有U系列低压低功耗版,而早有信息显示,H系列高性能版也在准备之中。
发布于 18:32&&|&&6400次阅读&&|&&2个意见
2月14日情人节似乎是一年中选择结婚最浪漫的一天。但一项研究显示,选择情人节结婚的情侣更有可能离婚。或许是因为情人节的情侣们更容易冲动,研究显示,这些情侣在婚前平均相处的时间都较短。这项由墨尔本大学主导的研究发现,2月14日结婚的人离婚的可能性要高出37%。
发布于 17:42&&|&&2133次阅读&&|&&0个意见
2月底MWC大会将在巴塞罗那开幕,不少厂商已经确定将在本次大会上推出新品,其中华硕将于2月28日凌晨2点30分举办发布新一代ZenFone系列智能手机。2月11日,外媒WinFuture带来了华硕ZenFone 5渲染图,如图所示,华硕ZenFone 5采用了类似iPhone X的刘海屏造型,背部配备双摄像头,呈竖形排列,和iPhone X一致,同时配有背部指纹识别,而且从渲染图来看,新机采用的是玻璃材质。
发布于 17:40&&|&&2959次阅读&&|&&0个意见
据外媒《英国每日邮报》报道,美国陆军正在测试一辆无人驾驶的悍马卡车,希望它能帮助那些被困在战场危险境地的士兵。这个被称为“Wingman”的悍马正在接受测试,看它能否准确识别和射击目标。安装在卡车顶部的是一个.50口径(12.7毫米)的机关枪和一个自主远程作战系统,与驻扎在附近的指挥和控制车辆通信。
发布于 17:39&&|&&1590次阅读&&|&&0个意见
日前,支付宝官方微博再次发文提醒用户,不要轻易加陌生人好友,以防上当受骗。该微博下面配图是媒体报道的“有网友为了集齐五福被骗了1000多元”事件。然而该事件发生在去年春节期间。
发布于 17:32&&|&&1619次阅读&&|&&1个意见
2月10日,阿里巴巴集团董事局主席马云出席了2018平昌冬奥会阿里巴巴展馆开馆仪式。期间,马云带着国际奥委会主席巴赫体验了天猫的虚拟试衣镜。另外,作为奥运历史上首个“未来商店”——天猫导购大屏也引发了很多关注。
发布于 17:27&&|&&1312次阅读&&|&&0个意见
随着春节的临近,一年一度的红包大战如约而至。去年春节期间,腾讯共派发了2.5亿现金红包和价值30亿的卡券礼包,与之相比,支付宝红包的玩法也毫不逊色,共派发2亿AR红包和五福现金红包。到了今年,这场硝烟味十足的红包大战已经进入了第五个年头。各大互联网平台又纷纷推出新动作,来入局2018年的红包大战。
发布于 17:25&&|&&3259次阅读&&|&&1个意见
此前魅族创始人黄章公开宣布,魅族下一代旗舰名为魅族15,同时还有大屏版魅族15 Plus,现在有关魅族新机的细节被曝光。据GinzChina.it报道,本次魅族一共准备了三款新机,除了魅族15、魅族15 Plus外,还有魅族15 Lite。其中魅族15和魅族15 Plus定位旗舰,魅族15 Lite定位中端。
发布于 16:25&&|&&9149次阅读&&|&&0个意见
据美国《世界日报》报道,为期减少带菌的埃及斑蚊和协助防疫,美国迈阿密卫生当局开始释出几亿只经过处理,没有生育能力的不孕蚊。美国南迈阿密市长日前召开记者会,当场释出一批样本蚊子。虽然释出的都是不会叮人的雄蚊,但在场的记者本能的伸手挥赶。市长史托达见状叮咛大家:“小心,不要伤到它们!”
发布于 15:49&&|&&2403次阅读&&|&&0个意见
近日,安徽蚌埠一男子因为父亲没有让他骑电瓶车,也没有给他买iPhone,就一怒之下烧了自己家。据@蚌埠公安在线通报,2月8日,蚌埠市经开公安分局接到一位市民的报警称:邻居家着火了。民警迅速赶到现场将火情控制住,可惜整个房子几乎烧空了。
发布于 15:47&&|&&6931次阅读&&|&&8个意见
2月11日下午消息,针对迅雷公司发布公告称摸金狗旗下P2P平台蜂鸟金融发生欠薪及经营困难,蜂鸟金融通过官方微信发布声明,称消息不实。蜂鸟金融表示:1.目前公司运转正常,而且收入情况良好,P2P没有发生任何欠薪或经营问题,最近还聘请了知名律师事务所进场尽调,积极准备合规备案事项;
发布于 15:47&&|&&1284次阅读&&|&&1个意见
2月11日消息,比特币中国股东杨林科称,BTCC股权100%转让给香港一家投资基金,原来四个最大股东,包括李启元、光速资本、杨林科、黄啸宇全部清仓股份套现。据悉,这笔交易没有达到百亿元,交易数据并未透露。
发布于 15:45&&|&&6441次阅读&&|&&0个意见
据英国《每日邮报》2月9日报道,根据自科学家最新研究,太阳11年活动周期的追踪方法已被发现。该周期与心跳类似,会经历活跃和安静期,也称为太阳活到极大期和极小期。在未来30年内,太阳可能会变黯,会使地球处于“迷你冰河期”。
发布于 15:44&&|&&1644次阅读&&|&&2个意见
在意大利,一名16岁的少年将他的母亲诉至法院,因母亲未经他同意的情况下在Facebook上发布他的照片。目前法院判定,该女子禁止在社交媒体上发布儿子的照片,并同时警告,如果她不执行,将面临1万欧元(约合7万7千元人民币)的罚款处罚。
发布于 15:41&&|&&2595次阅读&&|&&2个意见
2月11日消息,近日,武汉木兰公交客运有限公司与支付宝试点NFC乘公交功能,首批覆盖武汉市黄陂区11路、21路、PG3、PK3 路等四条公交线路。支付宝乘车码与NFC技术结合后,乘车时,持有NFC手机的乘客无需解锁手机,只需点亮手机屏幕,用支持NFC的手机触碰公交车上的NFC&机具,就能直接上车了,车费将从支付宝中自动扣除。
发布于 15:39&&|&&3358次阅读&&|&&2个意见
尽管日本是任天堂(Nintendo Corp.)、索尼(Sony Corp.)和万代(Bandai
Namco)、大型游戏迷以及个人明星游戏玩家等电子游戏巨头的大本营,但令人惊讶的是,它在电子竞技领域却远远落后于世界其他国家。但随着电子竞技可能会成为奥运会正式比赛项目,日本决心迎头赶上。
发布于 15:17&&|&&1069次阅读&&|&&0个意见
今日,中国信息通信研究院发布了《2018年1月国内手机市场运行分析报告》。报告显示,2018年1月,国内手机市场出货量3906.4万部,同比下降16.6%;上市新机型51款,同比下降19%。其中,智能手机出货量为3628.2万部,同比下降19.4%,占同期国内手机出货量的92.9%,其中Android手机出货量2945.7万部。
发布于 14:06&&|&&2366次阅读&&|&&2个意见
说起勒索病毒,大家可能常见的又是英文,又是比特币的界面,即使是想交赎金,按照流程走也比较麻烦。为了更加方便的勒索,黑客们搞了一次中国特色的勒索,界面如图下:
发布于 13:44&&|&&12554次阅读&&|&&4个意见
本周二,美国自动驾驶卡车系统研究公司Embark日完成了一次意义重大的测试,从西海岸的加利福尼亚州一路开往东海岸的佛罗里达州,创造了一次2400英里(约3864公里)的测试历史。在自动驾驶卡车行业中,Embark也成为了第一家穿越美国东西海岸的公司。
发布于 13:43&&|&&683次阅读&&|&&0个意见
意大利加密货币交易所BitGrail在其官网宣布,其价值1.7亿美元的Nano币(此前被称为RaiBlocks币)被盗,目前已上报监管部门,暂停所有代币交易业务。而BitGrail创始人弗朗西斯科·菲拉诺(Francesco
Firano)在Twitter公开表明交易所绝不会赔偿用户损失资金。
发布于 13:42&&|&&1241次阅读&&|&&0个意见
在上海市虹口区某办公大楼一间几十平方米的办公室里,错落着十几张简易的办公桌,桌上只有一些简单的办公配置,此外再无更多装饰。这几天正是上海最冷的时节,办公室里并不暖和,裹着厚厚羽绒服的张马丁说:“只要公社会员维持在一万人以上,并且政府没有强制关闭,我们就会坚持下去。”
发布于 13:41&&|&&1128次阅读&&|&&0个意见
2月9日晚间,证监会官网挂出了富士康A股上市最新消息,富士康工业互联网股份公司首次公开发行股票招股说明书。在预披露招股说明书(申报稿)显示,富士康股份拟在上海证券交易所上市。这也意味着,世界最大代工企业即将冲击A股上市。支持富士康A股上市的几大理由:
发布于 13:40&&|&&1149次阅读&&|&&0个意见
央广网北京2月11日消息(记者吴喆华)据中国之声《新闻纵横》报道,近日,有来自北京的家长反映,自己正在读高一的孩子在学校抽烟被老师发现了,通过询问后才知道,抽的烟是竟然是通过外卖平台购买的。据了解,这样的情况并不是少数,不少学生都是通过外卖平台购买到了香烟。
发布于 13:39&&|&&2698次阅读&&|&&0个意见
这锤子也是锤子得狠,改个铲铲名字
对文章:的评论
[s:哭]看到Annual Income那项我估计在座各位都活不长了。。。。
对文章:的评论
刚看完王老吉的贴,刚下的结论,老鼠实验不适用于人。
对文章:的评论
开了一年了,操控很好 -Forza Horizon 3 用户
对文章:的评论
jimmyfluore
国有国法,咖有咖规
对文章:的评论
Cloud_Atlas
“人工智障”果不其然。[s:黑]
对文章:的评论
“复兴号”从北京到上海跑一趟,单程1318公里,记录的数据达300多兆。相比之下,73万字的《红楼梦》所占数据空间仅有1.7兆。 亏你想的出来 这么比
来自湖北武汉的匿名人士对文章:的评论
程序员抢了一盒月饼被开除了,现在出了这么大的事,警告完事.
价值观进步真大啊.
来自湖北荆门的匿名人士对文章:的评论
然而国内都是 叉
来自河南安阳的匿名人士对文章:的评论
建议改名叫浏览器算了。
来自广东深圳的匿名人士对文章:的评论
饭店每天都要研究各种生物。
来自浙江温州的匿名人士对文章:的评论
刚刚还在微博看到这件事!豆瓣的评分机制本来就不好,连零分都没有,导致这样的片子只能打2分。。。。
来自广东广州的匿名人士对文章:的评论
时间就是金钱,效率就是生命。
来自重庆的匿名人士对文章:的评论
马的。我还以为是掉个大闸蟹下去夹娃娃呢。
来自四川成都的匿名人士对文章:的评论
刚建模,还没上色
来自北京的匿名人士对文章:的评论
如果用户发点不当的言论,责任也全是微博,这样可不可以?[s:汗]
来自辽宁沈阳的匿名人士对文章:的评论
全栈餐饮师
来自福建宁德的匿名人士对文章:的评论
速度太快,车厢外的三哥抓不住车厢怎么办?
来自北京的匿名人士对文章:的评论
越级管理本身就是错的,如果开错了人那就把开错人的人开掉,这才是老板该干的事
来自北京的匿名人士对文章:的评论
把加班时间说得这么清新脱俗?[s:贱笑]
来自广东潮州的匿名人士对文章:的评论
真是瞎眼了,六卡蓝宝石超白金显卡矿机,一台1.3万
来自上海的匿名人士对文章:的评论
这是典型的过河拆桥啊。
来自北京的匿名人士对文章:的评论
这设计还不错,脑残穿着掉进窨井后,雨衣就自动套在窨井口,提醒路人已经有脑残掉下去了,注意安全。
来自浙江杭州的匿名人士对文章:的评论
英语老师听闻雷军回来了,避而不见- [s:笑]
来自河南郑州的匿名人士对文章:的评论
有毒蚂蚁,这样一窝浮在水面上可以一窝端,泡酒去风湿
来自广东深圳的ios客户端用户对文章:的评论
700万的房子买不起 7000的iPhone还是买得起的
来自上海的ios客户端用户对文章:的评论
这下真的是祝有情人终成兄妹了。。。
来自浙江温州的匿名人士对文章:的评论
野外雅马哈便携汽油发电机才是王道,这货有个卵用
来自黑龙江哈尔滨的匿名人士对文章:的评论
“将智能手机放在孩子的背后,因为用户永远不会忘记自己的智能手机。”非常有道理
来自北京的ios客户端用户对文章:的评论
什么年代了,用长整形会死么?减法做之前比较一下会死么?可以看出这种系统都是外包了多少层做出来的,学校实验室里的小朋友们辛苦了。
来自北京的匿名人士对文章:的评论
道路曲折前景却光明,华为扎根美国是时间问题。
来自技术以外的各方面不确定性因素太多,并不看好。
华为现有的产品力面对作为科技大本营的美国还需要多加修炼。
相比美国,华为不妨将目光转换到其它国别市场。
阅读 (10033) 评论 (20)
阅读 (6912) 评论 (13)
阅读 (5007) 评论 (9)
阅读 (31316) 评论 (0)
阅读 (17714) 评论 (0)
阅读 (17113) 评论 (5)DKBA华为技术有限公司内部技术规范DKBA C语言编程规范日发布 日实施华为技术有限公司Huawei Technologies Co., Ltd.版权所有 侵权必究All rights reserved密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第2页,共61页Page 2 , Total61修订声明Revision declaration本规范拟制与解释部门:本规范的相关系列规范或文件:相关国际规范或文件一致性:替代或作废的其它规范或文件:相关规范或文件的相互关系:规范号主要起草部门专家主要评审部门专家修订情况DKBAxxxx.x-xxxx.xxPSST质量部:郭曙光网络:张伟周灿王晶陈艺彪IP开发部:薛治核心网:张小林王德喜李明胜软件公司:文 滔无线:刘爱华中研:谭洪PSST质量部:李重霄郭永生核心网:张进柏中研:张建保无线:苏光牛郑铭陶永祥软件公司:周代兵刘心红朱文琦网络:王玎黄维东49827IP开发部:饶远密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第3页,共61页Page 3 , Total61目 录Table of Contents0 规范制订说明 ................................................................................................................................ 50.1 前言 ...................................................................................................................................... 50.2 代码总体原则 ....................................................................................................................... 50.3 规范实施、解释 .................................................................................................................... 60.4 术语定义 ............................................................................................................................... 61 头文件 ........................................................................................................................................... 62 函数 ............................................................................................................................................. 123 标识符命名与定义 ....................................................................................................................... 213.1 通用命名规则 ..................................................................................................................... 213.2 文件命名规则 ..................................................................................................................... 233.3 变量命名规则 ..................................................................................................................... 233.4 函数命名规则 ..................................................................................................................... 243.5 宏的命名规则 ..................................................................................................................... 244 变量 ............................................................................................................................................. 255 宏、常量...................................................................................................................................... 286 质量保证...................................................................................................................................... 327 程序效率...................................................................................................................................... 368 注释 ............................................................................................................................................. 399 排版与格式 .................................................................................................................................. 4410 表达式 ..................................................................................................................................... 4611 代码编辑、编译 ...................................................................................................................... 4912 可测性 ..................................................................................................................................... 5013 安全性 ..................................................................................................................................... 5113.1 字符串操作安全 .................................................................................................................. 5113.2 整数安全 ............................................................................................................................. 5213.3 格式化输出安全 .................................................................................................................. 5613.4 文件I/O安全 ........................................................................................................................ 5713.5 其它 .................................................................................................................................... 5914 单元测试 ................................................................................................................................. 5915 可移植性 ................................................................................................................................. 6016 业界编程规范 .......................................................................................................................... 60密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第4页,共61页Page 4 , Total61C语言编程规范范 围:本规范适用于公司内使用C语言编码的所有软件。本规范自发布之日起生效,以后新编写的和修改的代码应遵守本规范。简 介:本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第5页,共61页Page 5 , Total610 规范制订说明0.1 前言为提高产品代码质量,指导广大软件开发人员编写出简洁、可维护、可靠、可测试、高效、可移植的代码,编程规范修订工作组分析、总结了我司的各种典型编码问题,并参考了业界编程规范近年来的成果,重新对我司1999年版编程规范进行了梳理、优化、刷新,编写了本规范。本规范将分为完整版和精简版,完整版将包括更多的样例、规范的解释以及参考材料(what & why),而精简版将只包含规则部分(what)以便查阅。在本规范的最后,列出了一些业界比较优秀的编程规范,作为延伸阅读参考材料。0.2 代码总体原则1、清晰第一清晰性是易于维护、易于重构的程序必需具备的特征。代码首先是给人读的,好的代码应当可以像文章一样发声朗诵出来。目前软件维护期成本占整个生命周期成本的40%~90%。根据业界经验,维护期变更代码的成本,小型系统是开发期的5倍,大型系统(100万行代码以上)可以达到100倍。业界的调查指出,开发组平均大约一半的人力用于弥补过去的错误,而不是添加新的功能来帮助公司提高竞争力。&程序必须为阅读它的人而编写,只是顺便用于机器执行。&&&Harold Abelson 和 Gerald Jay Sussman&编写程序应该以人为本,计算机第二。&&&Steve McConnell本规范通过后文中的原则(如头优秀的代码可以自我解释,不通过注释即可轻易读懂/头文件中适合放置接口的声明,不适合放置实现/除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音)、规则(如防止局部变量与全局变量同名)等说明清晰的重要性。一般情况下,代码的可阅读性高于性能,只有确定性能是瓶颈时,才应该主动优化。2、简洁为美简洁就是易于理解并且易于实现。代码越长越难以看懂,也就越容易在修改时引入错误。写的代码越多,意味着出错的地方越多,也就意味着代码的可靠性越低。因此,我们提倡大家通过编写简洁明了的代码来提升代码可靠性。废弃的代码(没有被调用的函数和全局变量)要及时清除,重复代码应该尽可能提炼成函数。本规范通过后文中的原则(如文件应当职责单一/一个函数仅完成一件功能)、规则(重复代码应该尽可能提炼成函数/避免函数过长,新增函数不超过50行)等说明简洁的重要性。3、选择合适的风格,与代码原有风格保持一致产品所有人共同分享同一种风格所带来的好处,远远超出为了统一而付出的代价。在公司已有编码规范的指导下,审慎地编排代码以使代码尽可能清晰,是一项非常重要的技能。如果重构/修改其他风格的代码时,比较明智的做法是根据现有代码的现有风格继续编写代码,或者使用格式转换工具进行转密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第6页,共61页Page 6 , Total61换成公司内部风格。0.3 规范实施、解释本规范制定了编写C语言程序的基本原则、规则和建议。本规范适用于公司内使用C语言编码的所有软件。本规范自发布之日起生效,对以后新编写的和修改的代码应遵守本规范。本规范由质量体系发布和维护。实施中遇到问题,可以到论坛http://hi3ms.huawei.com/group/1735/threads.html上讨论。在某些情况下(如BSP软件)需要违反本文档给出的规则时,相关团队必须通过一个正式的流程来评审、决策规则违反的部分,个体程序员不得违反本规范中的相关规则。0.4 术语定义原则:编程时必须坚持的指导思想。规则:编程时强制必须遵守的约定。建议:编程时必须加以考虑的约定。说明:对此原则/规则/建议进行必要的解释。示例:对此原则/规则/建议从正、反两个方面给出例子。延伸阅读材料:建议进一步阅读的参考材料。1 头文件背景对于C语言来说,头文件的设计体现了大部分的系统设计。不合理的头文件布局是编译时间过长的根因,不合理的头文件实际上不合理的设计。术语定义:依赖:本章节特指编译依赖。若x.h包含了y.h,则称作x依赖y。依赖关系会进行传导,如x.h包含y.h,而y.h又包含了z.h,则x通过y依赖了z。依赖将导致编译时间的上升。虽然依赖是不可避免的,也是必须的,但是不良的设计会导致整个系统的依赖关系无比复杂,使得任意一个文件的修改都要重新编译整个系统,导致编译时间巨幅上升。在一个设计良好的系统中,修改一个文件,只需要重新编译数个,甚至是一个文件。某产品曾经做过一个实验,把所有函数的实现通过工具注释掉,其编译时间只减少了不到10%,究其原因,在于A包含B,B包含C,C包含D,最终几乎每一个源文件都包含了项目组所有的头文件,从而导致绝大部分编译时间都花在解析头文件上。某产品更有一个&优秀实践&,用于将.c文件通过工具合并成一个比较大的.c文件,从而大幅度提高编译效率。其根本原因还是在于通过合并.c文件减少了头文件解析次数。但是,这样的&优秀实践&是对合理划分.c文件的一种破坏。大部分产品修改一处代码,都得需要编译整个工程,对于TDD之类的实践,要求对于模块级别的编译时间控制在秒级,即使使用分布式编译也难以实现,最终仍然需要合理的划分头文件、以及头文件之间的包含关系,从根本上降低编译时间。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第7页,共61页Page 7 , Total61《google C++ Style Guide》1.2 头文件依赖 章节也给出了类似的阐述:若包含了头文件aa.h,则就引入了新的依赖:一旦aa.h被修改,任何直接和间接包含aa.h代码都会被重新编译。如果aa.h又包含了其他头文件如bb.h,那么bb.h的任何改变都将导致所有包含了aa.h的代码被重新编译,在敏捷开发方式下,代码会被频繁构建,漫长的编译时间将极大的阻碍频繁构建。因此,我们倾向于减少包含头文件,尤其是在头文件中包含头文件,以控制改动代码后的编译时间。合理的头文件划分体现了系统设计的思想,但是从编程规范的角度看,仍然有一些通用的方法,用来合理规划头文件。本章节介绍的一些方法,对于合理规划头文件会有一定的帮助。原则1.1 头文件中适合放置接口的声明,不适合放置实现。说明:头文件是模块(Module)或单元(Unit)的对外接口。头文件中应放置对外部的声明,如对外提供的函数声明、宏定义、类型定义等。内部使用的函数(相当于类的私有方法)声明不应放在头文件中。内部使用的宏、枚举、结构定义不应放入头文件中。变量定义不应放在头文件中,应放在.c文件中。变量的声明尽量不要放在头文件中,亦即尽量不要使用全局变量作为接口。变量是模块或单元的内部实现细节,不应通过在头文件中声明的方式直接暴露给外部,应通过函数接口的方式进行对外暴露。 即使必须使用全局变量,也只应当在.c中定义全局变量,在.h中仅声明变量为全局的。延伸阅读材料:《C语言接口与实现》(David R. Hanson 著 傅蓉 周鹏 张昆琪 权威 译 机械工业出版社 2004年1月)(英文版: "C Interfaces and Implementations")原则1.2 头文件应当职责单一。说明:头文件过于复杂,依赖过于复杂是导致编译时间过长的主要原因。很多现有代码中头文件过大,职责过多,再加上循环依赖的问题,可能导致为了在.c中使用一个宏,而包含十几个头文件。示例:如下是某平台定义WORD类型的头文件:#include &VXWORKS.H&#include &KERNELLIB.H&#include &SEMLIB.H&#include &INTLIB.H&#include &TASKLIB.H&#include &MSGQLIB.H&#include &STDARG.H&#include &FIOLIB.H&#include &STDIO.H&#include &STDLIB.H&#include &CTYPE.H&#include &STRING.H&#include &ERRNOLIB.H&#include &TIMERS.H&#include &MEMLIB.H&#include &TIME.H&#include &WDLIB.H&#include &SYSLIB.H&#include &TASKHOOKLIB.H&#include &REBOOTLIB.H&&密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第8页,共61页Page 8 , Total61typedef unsigned short WORD;&这个头文件不但定义了基本数据类型WORD,还包含了stdio.h syslib.h等等不常用的头文件。如果工程中有10000个源文件,而其中100个源文件使用了stdio.h的printf,由于上述头文件的职责过于庞大,而WORD又是每一个文件必须包含的,从而导致stdio.h/syslib.h等可能被不必要的展开了9900次,大大增加了工程的编译时间。原则1.3 头文件应向稳定的方向包含。说明:头文件的包含关系是一种依赖,一般来说,应当让不稳定的模块依赖稳定的模块,从而当不稳定的模块发生变化时,不会影响(编译)稳定的模块。就我们的产品来说,依赖的方向应该是:产品依赖于平台,平台依赖于标准库。某产品线平台的代码中已经包含了产品的头文件,导致平台无法单独编译、发布和测试,是一个非常糟糕的反例。除了不稳定的模块依赖于稳定的模块外,更好的方式是两个模块共同依赖于接口,这样任何一个模块的内部实现更改都不需要重新编译另外一个模块。在这里,我们假设接口本身是最稳定的。延伸阅读材料:编者推荐开发人员使用&依赖倒置&原则,即由使用者制定接口,服务提供者实现接口,更具体的描述可以参见《敏捷软件开发:原则、模式与实践》(Robert C.Martin 著 邓辉 译 清华大学出版社2003年9月) 的第二部分&敏捷设计&章节。规则1.1 每一个.c文件应有一个同名.h文件,用于声明需要对外公开的接口。说明:如果一个.c文件不需要对外公布任何接口,则其就不应当存在,除非它是程序的入口,如main函数所在的文件。现有某些产品中,习惯一个.c文件对应两个头文件,一个用于存放对外公开的接口,一个用于存放内部需要用到的定义、声明等,以控制.c文件的代码行数。编者不提倡这种风格。这种风格的根源在于源文件过大,应首先考虑拆分.c文件,使之不至于太大。另外,一旦把私有定义、声明放到独立的头文件中,就无法从技术上避免别人include之,难以保证这些定义最后真的只是私有的。本规则反过来并不一定成立。有些特别简单的头文件,如命令ID定义头文件,不需要有对应的.c存在。示例:对于如下场景,如在一个.c中存在函数调用关系:void foo(){bar();}void bar(){D}必须在foo之前声明bar,否则会导致编译错误。这一类的函数声明,应当在.c的头部声明,并声明为static的,如下:static void bar();void foo(){bar();密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第9页,共61页Page 9 , Total61}void bar(){D}规则1.2 禁止头文件循环依赖。说明:头文件循环依赖,指a.h包含b.h,b.h包含c.h,c.h包含a.h之类导致任何一个头文件修改,都导致所有包含了a.h/b.h/c.h的代码全部重新编译一遍。而如果是单向依赖,如a.h包含b.h,b.h包含c.h,而c.h不包含任何头文件,则修改a.h不会导致包含了b.h/c.h的源代码重新编译。规则1.3 .c/.h文件禁止包含用不到的头文件。说明:很多系统中头文件包含关系复杂,开发人员为了省事起见,可能不会去一一钻研,直接包含一切想到的头文件,甚至有些产品干脆发布了一个god.h,其中包含了所有头文件,然后发布给各个项目组使用,这种只图一时省事的做法,导致整个系统的编译时间进一步恶化,并对后来人的维护造成了巨大的麻烦。规则1.4 头文件应当自包含。说明:简单的说,自包含就是任意一个头文件均可独立编译。如果一个文件包含某个头文件,还要包含另外一个头文件才能工作的话,就会增加交流障碍,给这个头文件的用户增添不必要的负担。示例:如果a.h不是自包含的,需要包含b.h才能编译,会带来的危害:每个使用a.h头文件的.c文件,为了让引入的a.h的内容编译通过,都要包含额外的头文件b.h。额外的头文件b.h必须在a.h之前进行包含,这在包含顺序上产生了依赖。注意:该规则需要与&.c/.h文件禁止包含用不到的头文件&规则一起使用,不能为了让a.h自包含,而在a.h中包含不必要的头文件。a.h要刚刚可以自包含,不能在a.h中多包含任何满足自包含之外的其他头文件。规则1.5 总是编写内部#include保护符(#define 保护)。说明:多次包含一个头文件可以通过认真的设计来避免。如果不能做到这一点,就需要采取阻止头文件内容被包含多于一次的机制。通常的手段是为每个文件配置一个宏,当头文件第一次被包含时就定义这个宏,并在头文件被再次包含时使用它以排除文件内容。所有头文件都应当使用#define 防止头文件被多重包含,命名格式为FILENAME_H,为了保证唯一性,更好的命名是PROJECTNAME_PATH_FILENAME_H。注:没有在宏最前面加上&_",即使用FILENAME_H代替_FILENAME_H_,是因为一般以"_"和&__"开头的标识符为系统保留或者标准库使用,在有些静态检查工具中,若全局可见的标识符以"_"开头会给出告警。定义包含保护符时,应该遵守如下规则:1)保护符使用唯一名称;2)不要在受保护部分的前后放置代码或者注释。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第10页,共61页Page 10 , Total61示例:假定VOS工程的timer模块的timer.h,其目录为VOS/include/timer/timer.h,应按如下方式保护:#ifndef VOS_INCLUDE_TIMER_TIMER_H#define VOS_INCLUDE_TIMER_TIMER_H...#endif也可以使用如下简单方式保护:#ifndef TIMER_H#define TIMER_H..#endif例外情况:头文件的版权声明部分以及头文件的整体注释部分(如阐述此头文件的开发背景、使用注意事项等)可以放在保护符(#ifndef XX_H)前面。规则1.6 禁止在头文件中定义变量。说明:在头文件中定义变量,将会由于头文件被其他.c文件包含而导致变量重复定义。规则1.7 只能通过包含头文件的方式使用其他.c提供的接口,禁止在.c中通过extern的方式使用外部函数接口、变量。说明:若a.c使用了b.c定义的foo()函数,则应当在b.h中声明extern int foo(int input);并在a.c中通过#include &b.h&来使用foo。禁止通过在a.c中直接写extern int foo(int input);来使用foo,后面这种写法容易在foo改变时可能导致声明和定义不一致。规则1.8 禁止在extern "C"中包含头文件。说明:在extern "C"中包含头文件,会导致extern "C"嵌套,Visual Studio对extern "C"嵌套层次有限制,嵌套层次太多会编译错误。在extern "C"中包含头文件,可能会导致被包含头文件的原有意图遭到破坏。例如,存在a.h和b.h两个头文件:#ifndef A_H__#define A_H__#ifdef __cplusplusvoid foo(int);#define a(value) foo(value)#elsevoid a(int)#endif#endif /* A_H__ */#ifndef B_H__#define B_H__#ifdef __cplusplusextern "C" {#endif#include "a.h"void b();#ifdef __cplusplus}#endif#endif /* B_H__ */使用C++预处理器展开b.h,将会得到密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第11页,共61页Page 11 , Total61extern "C" {void foo(int);void b();}按照a.h作者的本意,函数foo是一个C++自由函数,其链接规范为"C++"。但在b.h中,由于#include "a.h"被放到了extern "C" { }的内部,函数foo的链接规范被不正确地更改了。示例:错误的使用方式:extern &C&{#include &xxx.h&...}正确的使用方式:#include &xxx.h&extern &C&{...}建议1.1 一个模块通常包含多个.c文件,建议放在同一个目录下,目录名即为模块名。为方便外部使用者,建议每一个模块提供一个.h,文件名为目录名。说明:需要注意的是,这个.h并不是简单的包含所有内部的.h,它是为了模块使用者的方便,对外整体提供的模块接口。以Google test(简称GTest)为例,GTest作为一个整体对外提供C++单元测试框架,其1.5版本的gtest工程下有6个源文件和12个头文件。但是它对外只提供一个gtest.h,只要包含gtest.h即可使用GTest提供的所有对外提供的功能,使用者不必关系GTest内部各个文件的关系,即使以后GTest的内部实现改变了,比如把一个源文件c拆成两个源文件,使用者也不必关心,甚至如果对外功能不变,连重新编译都不需要。对于有些模块,其内部功能相对松散,可能并不一定需要提供这个.h,而是直接提供各个子模块或者.c的头文件。比如产品普遍使用的VOS,作为一个大模块,其内部有很多子模块,他们之间的关系相对比较松散,就不适合提供一个vos.h。而VOS的子模块,如Memory(仅作举例说明,与实际情况可能有所出入),其内部实现高度内聚,虽然其内部实现可能有多个.c和.h,但是对外只需要提供一个Memory.h声明接口。建议1.2 如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的.h,文件名为子模块名。说明:降低接口使用者的编写难度。建议1.3 头文件不要使用非习惯用法的扩展名,如.inc。说明:目前很多产品中使用了.inc作为头文件扩展名,这不符合c语言的习惯用法。在使用.inc作为头文件扩展名的产品,习惯上用于标识此头文件为私有头文件。但是从产品的实际代码来看,这一条并没有被遵守,一个.inc文件被多个.c包含比比皆是。本规范不提倡将私有定义单独放在头文件中,具密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第12页,共61页Page 12 , Total61体见 规则1.1。除此之外,使用.inc还导致source insight、Visual stduio等IDE工具无法识别其为头文件,导致很多功能不可用,如&跳转到变量定义处&。虽然可以通过配置,强迫IDE识别.inc为头文件,但是有些软件无法配置,如Visual Assist只能识别.h而无法通过配置识别.inc。建议1.4 同一产品统一包含头文件排列方式。说明:常见的包含头文件排列方式:功能块排序、文件名升序、稳定度排序。示例1:以升序方式排列头文件可以避免头文件被重复包含,如:#include &a.h&#include &b.h&#include &c/d.h&#include &c/e.h&#include &f.h&示例2:以稳定度排序,建议将不稳定的头文件放在前面,如把产品的头文件放在平台的头文件前面,如下:#include &product.h&#include &platform.h&相对来说,product.h修改的较为频繁,如果有错误,不必编译platform.h就可以发现product.h的错误,可以部分减少编译时间。2 函数背景函数设计的精髓:编写整洁函数,同时把代码有效组织起来。整洁函数要求:代码简单直接、不隐藏设计者的意图、用干净利落的抽象和直截了当的控制语句将函数有机组织起来。代码的有效组织包括:逻辑层组织和物理层组织两个方面。逻辑层,主要是把不同功能的函数通过某种联系组织起来,主要关注模块间的接口,也就是模块的架构。物理层,无论使用什么样的目录或者名字空间等,需要把函数用一种标准的方法组织起来。例如:设计良好的目录结构、函数名字、文件组织等,这样可以方便查找。原则2.1 一个函数仅完成一件功能。说明:一个函数实现多个功能给开发、使用、维护都带来很大的困难。将没有关联或者关联很弱的语句放到同一函数中,会导致函数职责不明确,难以理解,难以测试和改动。案例:realloc。在标准C语言中,realloc是一个典型的不良设计。这个函数基本功能是重新分配内存,但它承担了太多的其他任务:如果传入的指针参数为NULL就分配内存,如果传入的大小参数为0就释放内存,如果可行则就地重新分配,如果不行则移到其他地方分配。如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回NULL,而原来的内存块保持不变。这个函数不易扩展,容易导致问题。例如下面代码容易导致内存泄漏:char *buffer = (char *)malloc(XXX_SIZE);.....密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第13页,共61页Page 13 , Total61buffer = (char *)realloc(buffer, NEW_SIZE);如果没有足够可用的内存用来完成重新分配,函数返回为NULL,导致buffer原来指向的内存被丢失。延伸阅读材料:《敏捷软件开发:原则、模式与实践》 第八章,单一职责原则(SRP)原则2.2 重复代码应该尽可能提炼成函数。说明:重复代码提炼成函数可以带来维护成本的降低。重复代码是我司不良代码最典型的特征之一。在&代码能用就不改&的指导原则之下,大量的烟囱式设计及其实现充斥着各产品代码之中。新需求增加带来的代码拷贝和修改,随着时间的迁移,产品中堆砌着许多类似或者重复的代码。项目组应当使用代码重复度检查工具,在持续集成环境中持续检查代码重复度指标变化趋势,并对新增重复代码及时重构。当一段代码重复两次时,即应考虑消除重复,当代码重复超过三次时,应当立刻着手消除重复。一般情况下,可以通过提炼函数的形式消除重复代码。示例:UC ccb_aoc_process( ){... ...struct AOC_E1_E7 aoc_e1_e7;aoc_e1_e7.aoc = 0;aoc_e1_e7.e[0] = 0;... ... //aoc_e1_e7.e[i]从到赋值,下同aoc_e1_e7.e[6] = 0;aoc_e1_e7.tariff_rate = 0;... ...if (xxx){if (xxx){aoc_e1_e7.e[0] = 0;... ...aoc_e1_e7.e[6] = 0;aoc_e1_e7.tariff_rate = 0;}... ...}else if (xxx){if (xxx){aoc_e1_e7.e[0] = 0;... ...aoc_e1_e7.e[6] = 0;密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第14页,共61页Page 14 , Total61aoc_e1_e7.tariff_rate = 0;}ccb_caller_e1 = aoc_e1_e7.e[0];... ...ccb_caller_e7 = aoc_e1_e7.e[6];ccb_caller_tariff_rate = aoc_e1_e7.tariff_... ...}... ...if (xxx){if (xxx){if (xxx){aoc_e1_e7.e[0] = 0;... ...aoc_e1_e7.e[6] = 0;aoc_e1_e7.tariff_rate = 0;}... ...}else if (xxx){if (xxx){aoc_e1_e7.e[0] = 0;... ...aoc_e1_e7.e[6] = 0;aoc_e1_e7.tariff_rate = 0;}ccb_caller_e1 = aoc_e1_e7.e[0];... ...ccb_caller_e7 = aoc_e1_e7.e[6];ccb_caller_tariff_rate = aoc_e1_e7.tariff_... ...}return 1;}else{return 0;密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第15页,共61页Page 15 , Total61}}刺鼻的代码坏味充斥着这个函数。红色字体的部分是简单的代码重复,粗体字部分是代码结构的重复,将重复部分提炼成一个函数即可消除重复。规则2.1 避免函数过长,新增函数不超过50行(非空非注释行)。说明:本规则仅对新增函数做要求,对已有函数修改时,建议不增加代码行。过长的函数往往意味着函数功能不单一,过于复杂(参见原则2.1:一个函数只完成一个功能)。函数的有效代码行数,即NBNC(非空非注释行)应当在[1,50]区间。例外:某些实现算法的函数,由于算法的聚合性与功能的全面性,可能会超过50行。延伸阅读材料:业界普遍认为一个函数的代码行不要超过一个屏幕,避免来回翻页影响阅读;一般的代码度量工具建议都对此进行检查,例如Logiscope的函数度量:"Number of Statement" (函数中的可执行语句数)建议不超过20行,QA C建议一个函数中的所有行数(包括注释和空白行)不超过50行。规则2.2 避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层。说明:本规则仅对新增函数做要求,对已有的代码建议不增加嵌套层次。函数的代码块嵌套深度指的是函数中的代码控制块(例如:if、for、while、switch等)之间互相包含的深度。每级嵌套都会增加阅读代码时的脑力消耗,因为需要在脑子里维护一个&栈&(比如,进入条件语句、进入循环&&)。应该做进一步的功能分解,从而避免使代码的阅读者一次记住太多的上下文。优秀代码参考值:[1, 4]。示例:如下代码嵌套深度为5。void serial (void){if (!Received){TmoCount = 0;switch (Buff){case AISGFLG:if ((TiBuff.Count & 3)&& ((TiBuff.Buff[0] == 0xff) || (TiBuf.Buff[0] == CurPa.ADDR))){Flg7E =Received =}else{TiBuff.Count = 0;Flg7D =Flg7E =}default:}}}密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第16页,共61页Page 16 , Total61规则2.3 可重入函数应避免使用共享变量;若需要使用,则应通过互斥手段(关中断、信号量)对其加以保护。说明:可重入函数是指可能被多个任务并发调用的函数。在多任务操作系统中,函数具有可重入性是多个任务可以共用此函数的必要条件。共享变量指的全局变量和static变量。编写C语言的可重入函数时,不应使用static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。示例:函数square_exam返回g_exam平方值。那么如下函数不具有可重入性。int g_unsigned int example( int para ){g_exam = // (**)temp = square_exam ( );}此函数若被多个线程调用的话,其结果可能是未知的,因为当(**)语句刚执行完后,另外一个使用本函数的线程可能正好被激活,那么当新激活的线程执行到此函数时,将使g_exam赋于另一个不同的para值,所以当控制重新回到&temp =square_exam ( )&后,计算出的temp很可能不是预想中的结果。此函数应如下改进。int g_unsigned int example( int para ){[申请信号量操作] // 若申请不到&信号量&,说明另外的进程正处于g_exam = //给g_exam赋值并计算其平方过程中(即正在使用此temp = square_exam( ); // 信号),本进程必须等待其释放信号后,才可继[释放信号量操作] // 续执行。其它线程必须等待本线程释放信号量后// 才能再使用本信号。}规则2.4 对参数的合法性检查,由调用者负责还是由接口函数负责,应在项目组/模块内应统一规定。缺省由调用者负责。说明:对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这一必要的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。示例:下面红色部分的代码在每一个函数中都写了一次,导致代码有较多的冗余。如果函数的参数比较多,而且判断的条件比较复杂(比如:一个整形数字需要判断范围等),那么冗余的代码会大面积充斥着业务代码。void PidMsgProc(MsgBlock *Msg){MsgProcItem *func = NULL;密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第17页,共61页Page 17 , Total61if (Msg == NULL){}... ...GetMsgProcFun(Msg, &func);func(Msg);}int GetMsgProcFun(MsgBlock *Msg, MsgProcItem **func){if (Msg == NULL){return 1;}... ...*func = VOS_NULL_PTR;for (Index = 0; Index & NELEM(g_MsgProcTable); Index++){if ((g_MsgProcTable[Index].FlowType == Msg-&FlowType)&& (g_MsgProcTable[Index].Status == Msg-&Status)&& (g_MsgProcTable[Index].MsgType == Msg-&MsgType)){*func = &(g_MsgProcTable[Index]);return 0;}}return 1;}int ServiceProcess(int CbNo, MsgBlock *Msg){if ( Msg == NULL){return 1;}... ...// 业务处理代码... ...return 0;}规则2.5 对函数的错误返回码要全面处理。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第18页,共61页Page 18 , Total61说明:一个函数(标准库中的函数/第三方库函数/用户定义的函数)能够提供一些指示错误发生的方法。这可以通过使用错误标记、特殊的返回数据或者其他手段,不管什么时候函数提供了这样的机制,调用程序应该在函数返回时立刻检查错误指示。示例:下面的代码导致宕机FILE *fp = fopen( "./writeAlarmLastTime.log","r");if(fp == NULL){}char buff[128] = "";fscanf(fp,&%s&, buff); /* 读取最新的告警时间;由于文件writeAlarmLastTime.log为空,导致buff为空 */fclose(fp);long fileTime = getAlarmTime(buff); /* 解析获取最新的告警时间;getAlarmTime函数未检查buff指针,导致宕机 */正确写法:FILE *fp = fopen( "./writeAlarmLastTime.log","r");if(fp == NULL){}char buff[128] = "";if (fscanf(fp,&%s&,buff) == EOF) //检查函数fscanf的返回值,确保读到数据{fclose(fp);}fclose(fp);long fileTime = getAlarmTime(buff); //解析获取最新的告警时间;规则2.6 设计高扇入,合理扇出(小于7)的函数。说明:扇出是指一个函数直接调用(控制)其它函数的数目,而扇入是指有多少上级函数调用它。扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数;而扇出过小,例如:总是1,表明函数的调用层次可能过多,这样不利于程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。通常函数比较合理的扇出(调度函数除外)通常是3~5。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第19页,共61页Page 19 , Total61扇出太大,一般是由于缺乏中间层次,可适当增加中间层次的函数。扇出太小,可把下级函数进一步分解多个函数,或合并到上级函数中。当然分解或合并函数时,不能改变要实现的功能,也不能违背函数间的独立性。扇入越大,表明使用此函数的上级函数越多,这样的函数使用效率高,但不能违背函数间的独立性而单纯地追求高扇入。公共模块中的函数及底层函数应该有较高的扇入。较良好的软件结构通常是顶层函数的扇出较高,中层函数的扇出较少,而底层函数则扇入到公共模块中。延伸阅读材料:扇入(Fan-in)和扇出(Fan-out)是Henry和Kafura在1981年引入,用来说明模块间的耦合(coupling),后面人们扩展到函数/方法、模块/类、包等。The Fan-in (Informational fan-in) metric measures the fan-in of a module. The fan-in of a module A is the number of modules that pass control into module A.The Fan-out metric measures the number of the number of modules that are called by a given module.规则2.7 废弃代码(没有被调用的函数和变量)要及时清除。说明:程序中的废弃代码不仅占用额外的空间,而且还常常影响程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。建议2.1 函数不变参数使用const。说明:不变的值更易于理解/跟踪和分析,把const作为默认选项,在编译时会对其进行检查,使代码更牢固/更安全。示例:C99标准 7.21.4.4 中strncmp 的例子,不变参数声明为const。int strncmp(const char *s1, const char *s2, register size_t n){register unsigned char u1, u2;while (n-- & 0){u1 = (unsigned char) *s1++;u2 = (unsigned char) *s2++;if (u1 != u2){return u1 - u2;}if (u1 == '\0'){return 0;}}return 0;}延伸阅读:pc-lint 8.0的帮助材料(pc-lint.pdf)11.4 const Checking密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第20页,共61页Page 20 , Total61建议2.2 函数应避免使用全局变量、静态局部变量和I/O操作,不可避免的地方应集中使用。说明:带有内部&存储器&的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。这样的函数既不易于理解又不利于测试和维护。在C语言中,函数的static局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类,则返回为错针。示例:如下函数,其返回值(即功能)是不可预测的。unsigned int integer_sum( unsigned int base ){static unsigned int sum = 0;// 注意,是static类型的。// 若改为auto类型,则函数即变为可预测。for (index = 1; index &= index++){sum +=}}延伸阅读材料:erlang语言中关于dirty的概念,函数式语言的优势建议2.3 检查函数所有非参数输入的有效性,如数据文件、公共变量等。说明:函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,即非参数输入。函数在使用输入参数之前,应进行有效性检查。示例:下面的代码导致宕机hr = root_node-&get_first_child(&log_item); // list.xml 为空,导致读出log_item为空&..hr = log_item-&get_next_sibling(&media_next_node); // log_item为空,导致宕机正确写法:确保读出的内容非空。hr = root_node-&get_first_child(&log_item);&..if (log_item == NULL) //确保读出的内容非空{return retV}hr = log_item-&get_next_sibling(&media_next_node);建议2.4 函数的参数个数不超过5个。说明:函数的参数过多,会使得该函数易于受外部(其他部分的代码)变化的影响,从而影响维护工作。函数的参数过多同时也会增大测试的工作量。函数的参数个数不要超过5个,如果超过了建议拆分为不同函数。建议2.5 除打印类函数外,不要使用可变长参函数。说明:可变长参函数的处理过程比较复杂容易引入错误,而且性能也比较低,使用过多的可变长参函密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第21页,共61页Page 21 , Total61数将导致函数的维护难度大大增加。建议2.6 在源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加static关键字。说明:如果一个函数只是在同一文件中的其他地方调用,那么就用static声明。使用static确保只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性。建议定义一个STATIC宏,在调试阶段,将STATIC定义为static,版本发布时,改为空,以便于后续的打热补丁等操作。#ifdef _DEBUG#define STATIC static#else#define STATIC#endif3 标识符命名与定义3.1 通用命名规则目前比较使用的如下几种命名风格:unix like风格:单词用小写字母,每个单词直接用下划线&_"分割,例如text_mutex,kernel_text_address。Windows风格:大小写字母混用,单词连在一起,每个单词首字母大写。不过Windows风格如果遇到大写专有用语时会有些别扭,例如命名一个读取RFC文本的函数,命令为ReadRFCText,看起来就没有unix like的read_rfc_text清晰了。匈牙利命名法是计算机程序设计中的一种命名规则,用这种方法命名的变量显示了其数据类型。匈牙利命名主要包括三个部分:基本类型、一个或更多的前缀、一个限定词。这种命令法最初在20世纪80年代的微软公司广泛使用,并在win32API和MFC库中广泛的使用,但匈牙利命名法存在较多的争议,例如:.NET Framework,微软新的软件开发平台,除了接口类型一般不适用匈牙利命名法。.NET Framework指导方针建议程序员不要用匈牙利命名法,但是没有指明不要用系统匈牙利命名法还是匈牙利应用命名法,或者是两者都不要用。与此对比,Java的标准库中连接口类型也不加前缀。(来源http://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9%E5%91%BD%E5%90%8D%E6%B3%95)匈牙利命名法更多的信息见http://en.wikipedia.org/wiki/Hungarian_notation。标识符的命名规则历来是一个敏感话题,典型的命名风格如unix风格、windows风格等等,从来无法达成共识。实际上,各种风格都有其优势也有其劣势,而且往往和个人的审美观有关。我们对标识符定义主要是为了让团队的代码看起来尽可能统一,有利于代码的后续阅读和修改,产品可以根据自己的实际需要指定命名风格,规范中不再做统一的规定。原则3.1 标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。说明:尽可能给出描述性名称,不要节约空间,让别人很快理解你的代码更重要。示例:好的命名:密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第22页,共61页Page 22 , Total61int error_int number_of_completed_不好的命名:使用模糊的缩写或随意的字符:int n_comp_原则3.2 除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音。说明:较短的单词可通过去掉&元音&形成缩写,较长的单词可取单词的头几个字母形成缩写,一些单词有大家公认的缩写,常用单词的缩写必须统一。协议中的单词的缩写与协议保持一致。对于某个系统使用的专用缩写应该在注视或者某处做统一说明。示例:一些常见可以缩写的例子:argument 可缩写为 argbuffer 可缩写为 buffclock 可缩写为 clkcommand 可缩写为 cmdcompare 可缩写为 cmpconfiguration 可缩写为 cfgdevice 可缩写为 deverror 可缩写为 errhexadecimal 可缩写为 hexincrement 可缩写为 inc、initialize 可缩写为 initmaximum 可缩写为 maxmessage 可缩写为 msgminimum 可缩写为 minparameter 可缩写为 paraprevious 可缩写为 prevregister 可缩写为 regsemaphore 可缩写为 semstatistic 可缩写为 statsynchronize 可缩写为 synctemp 可缩写为 tmp规则3.1 产品/项目组内部应保持统一的命名风格。说明:Unix like和windows like风格均有其拥趸,产品应根据自己的部署平台,选择其中一种,并在产品内部保持一致。例外:即使产品之前使用匈牙利命名法,新代码也不应当使用。建议3.1 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。示例:add/remove begin/end create/destroy密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第23页,共61页Page 23 , Total61insert/delete first/last get/releaseincrement/decrement put/get add/deletelock/unlock open/close min/maxold/new start/stop next/previoussource/target show/hide send/receivesource/destination copy/paste up/down建议3.2 尽量避免名字中出现数字编号,除非逻辑上的确需要编号。示例:如下命名,使人产生疑惑。#define EXAMPLE_0_TEST_#define EXAMPLE_1_TEST_应改为有意义的单词命名#define EXAMPLE_UNIT_TEST_#define EXAMPLE_ASSERT_TEST_建议3.3 标识符前不应添加模块、项目、产品、部门的名称作为前缀。说明:很多已有代码中已经习惯在文件名中增加模块名,这种写法类似匈牙利命名法,导致文件名不可读,并且带来带来如下问题:? 第一眼看到的是模块名,而不是真正的文件功能,阻碍阅读;? 文件名太长;? 文件名和模块绑定,不利于维护和移植。若foo.c进行重构后,从a模块挪到b模块,若foo.c中有模块名,则需要将文件名从a_module_foo.c改为b_module_foo.c建议3.4 平台/驱动等适配代码的标识符命名风格保持和平台/驱动一致。说明:涉及到外购芯片以及配套的驱动,这部分的代码变动(包括为产品做适配的新增代码),应该保持原有的风格。建议3.5 重构/修改部分代码时,应保持和原有代码的命名风格一致。说明:根据源代码现有的风格继续编写代码,有利于保持总体一致。3.2 文件命名规则建议3.6 文件命名统一采用小写字符。说明:因为不同系统对文件名大小写处理会不同(如MS的DOS、Windows系统不区分大小写,但是Linux系统则区分),所以代码文件命名建议统一采用全小写字母命名。3.3 变量命名规则规则3.2 全局变量应增加&g_&前缀。规则3.3 静态变量应增加&s_&前缀。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第24页,共61页Page 24 , Total61说明:增加g_前缀或者s_前缀,原因如下:首先,全局变量十分危险,通过前缀使得全局变量更加醒目,促使开发人员对这些变量的使用更加小心。其次,从根本上说,应当尽量不使用全局变量,增加g_和s_前缀,会使得全局变量的名字显得很丑陋,从而促使开发人员尽量少使用全局变量。规则3.4 禁止使用单字节命名变量,但允许定义i、j、k作为局部循环变量。建议3.7 不建议使用匈牙利命名法。说明:变量命名需要说明的是变量的含义,而不是变量的类型。在变量命名前增加类型说明,反而降低了变量的可读性;更麻烦的问题是,如果修改了变量的类型定义,那么所有使用该变量的地方都需要修改。匈牙利命名法源于微软,然而却被很多人以讹传讹的使用。而现在即使是微软也不再推荐使用匈牙利命名法。历来对匈牙利命名法的一大诟病,就是导致了变量名难以阅读,这和本规范的指导思想也有冲突,所以本规范特意强调,变量命名不应采用匈牙利命名法,而应想法使变量名为一个有意义的词或词组,方便代码的阅读。建议3.8 使用名词或者形容词+名词方式命名变量。3.4 函数命名规则建议3.9 函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构。示例:找到当前进程的当前目录DWORD GetCurrentDirectory( DWORD BufferLength, LPTSTR Buffer );建议3.10 函数指针除了前缀,其他按照函数的命名规则命名。3.5 宏的命名规则规则3.5 对于数值或者字符串等等常量的定义,建议采用全大写字母,单词之间加下划线&_"的方式命名(枚举同样建议使用此方式定义)。示例:#define PI_ROUNDED 3.14规则3.6 除了头文件或编译开关等特殊标识定义,宏定义不能使用下划线&_"开头和结尾。说明:一般来说,"_"开头、结尾的宏都是一些内部的定义,ISO/IEC 9899(俗称C99)中有如下的描述(6.10.8 Predefined macro names):None of these macro names(这里上面是一些内部定义的宏的描述), nor the identifier defined, shall be the subject of a #define or a #undef preprocessing directive. Any other predefined macro names shall begin with a leading underscore followed by an uppercase letter or a second underscore.密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第25页,共61页Page 25 , Total61延伸阅读材料:《代码大全第2版》(Steve McConnell 著 金戈/汤凌/陈硕/张菲 译 电子工业出版社 2006年3月)"第11章变量命的力量"。4 变量原则4.1 一个变量只有一个功能,不能把一个变量用作多种用途。说明:一个变量只用来表示一个特定功能,不能把一个变量作多种用途,即同一变量取值不同时,其代表的意义也不同。示例:具有两种功能的反例WORD DelRelTimeQue(void){WORD LLocate = 3;Locate = DeleteFromQue(Locate); /* Locate具有两种功能:位置和函数DeleteFromQue的返回值 */return L}正确做法:使用两个变量WORD DelRelTimeQue(void){WORD RWORD LLocate = 3;Ret = DeleteFromQue(Locate);return R}原则4.2 结构功能单一;不要设计面面俱到的数据结构。说明:相关的一组信息才是构成一个结构体的基础,结构的定义应该可以明确的描述一个对象,而不是一组相关性不强的数据的集合。设计结构时应力争使结构代表一种现实事务的抽象,而不是同时代表多种。结构中的各元素应代表同一事务的不同侧面,而不应把描述没有关系或关系很弱的不同事务的元素放到同一结构中。示例:如下结构不太清晰、合理。typedef struct STUDENT_STRU{unsigned char name[32]; /* student's name */ /* student's age */ /* student's sex, as follows */密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第26页,共61页Page 26 , Total61/* 0 - FEMALE; 1 - MALE */unsigned char teacher_name[32]; /* the student teacher's name */unsigned char teacher_ /* his teacher sex */} STUDENT;若改为如下,会更合理些。typedef struct TEACHER_STRU{unsigned char name[32]; /* teacher name */ /* teacher sex, as follows *//* 0 - FEMALE; 1 - MALE */unsigned int teacher_ /* teacher index */} TEACHER;typedef struct STUDENT_STRU{unsigned char name[32]; /* student's name */ /* student's age */ /* student's sex, as follows *//* 0 - FEMALE; 1 - MALE */unsigned int teacher_ /* his teacher index */} STUDENT;原则4.3 不用或者少用全局变量。说明:单个文件内部可以使用static的全局变量,可以将其理解为类的私有成员变量。全局变量应该是模块的私有数据,不能作用对外的接口使用,使用static类型定义,可以有效防止外部文件的非正常访问,建议定义一个STATIC宏,在调试阶段,将STATIC定义为static,版本发布时,改为空,以便于后续的打补丁等操作。#ifdef _DEBUG#define STATIC static#else#define STATIC#endif直接使用其他模块的私有数据,将使模块间的关系逐渐走向&剪不断理还乱&的耦合状态,这种情形是不允许的。规则4.1 防止局部变量与全局变量同名。说明:尽管局部变量和全局变量的作用域不同而不会发生语法错误,但容易使人误解。规则4.2 通讯过程中使用的结构,必须注意字节序。说明:通讯报文中,字节序是一个重要的问题,我司设备使用的cpu类型复杂多样,大小端、32位/64位的处理器也都有,如果结构会在报文交互过程中使用,必须考虑字节序问题。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第27页,共61页Page 27 , Total61由于位域在不同字节序下,表现看起来差别更大,所以更需要注意。对于这种跨平台的交互,数据成员发送前,都应该进行主机序到网络序的转换;接收时,也必须进行网络序到主机序的转换。规则4.3 严禁使用未经初始化的变量作为右值。说明:坚持建议4.3(在首次使用前初始化变量,初始化的地方离使用的地方越近越好。)可以有效避免未初始化错误。建议4.1 构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的全局变量,防止多个不同模块或函数都可以修改、创建同一全局变量的现象。说明:降低全局变量耦合度。建议4.2 使用面向接口编程思想,通过API访问数据:如果本模块的数据需要对外部模块开放,应提供接口函数来设置、获取,同时注意全局数据的访问互斥。说明:避免直接暴露内部数据给外部模型使用,是防止模块间耦合最简单有效的方法。定义的接口应该有比较明确的意义,比如一个风扇管理功能模块,有自动和手动工作模式,那么设置、查询工作模块就可以定义接口为SetFanWorkMode,GetFanWorkMode;查询转速就可以定义为GetFanSpeed;风扇支持节能功能开关,可以定义EnabletFanSavePower等等。建议4.3 在首次使用前初始化变量,初始化的地方离使用的地方越近越好。说明:未初始化变量是C和C++程序中错误的常见来源。在变量首次使用前确保正确初始化。在较好的方案中,变量的定义和初始化要做到亲密无间。示例://不可取的初始化:无意义的初始化int speedup_factor = 0;if (condition){speedup_factor = 2;}else{speedup_factor = -1;}//不可取的初始化:初始化和声明分离int speedup_if (condition){speedup_factor = 2;}else{speedup_factor = -1;}//较好的初始化:使用默认有意义的初始化密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第28页,共61页Page 28 , Total61int speedup_factor = -1;if (condition){speedup_factor = 2;}//较好的初始化使用?:减少数据流和控制流的混合int speedup_factor = condition?2:-1;//较好的初始化:使用函数代替复杂的计算流int speedup_factor = ComputeSpeedupFactor();建议4.4 明确全局变量的初始化顺序,避免跨模块的初始化依赖。说明:系统启动阶段,使用全局变量前,要考虑到该全局变量在什么时候初始化,使用全局变量和初始化全局变量,两者之间的时序关系,谁先谁后,一定要分析清楚,不然后果往往是低级而又灾难性的。建议4.5 尽量减少没有必要的数据类型默认转换与强制转换。说明:当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节若考虑不周,就很有可能留下隐患。示例:如下赋值,多数编译器不产生告警,但值的含义还是稍有变化。unsch = -1;exam = // 编译器不产生告警,此时exam为0xFFFF。5 宏、常量规则5.1 用宏定义表达式时,要使用完备的括号。说明:因为宏只是简单的代码替换,不会像函数一样先将参数计算后,再传递。示例:如下定义的宏都存在一定的风险#define RECTANGLE_AREA(a, b) a * b#define RECTANGLE_AREA(a, b) (a * b)#define RECTANGLE_AREA(a, b) (a) * (b)正确的定义应为:#define RECTANGLE_AREA(a, b) ((a) * (b))这是因为:如果定义#define RECTANGLE_AREA(a, b) a * b 或#define RECTANGLE_AREA(a, b) (a * b)则c/RECTANGLE_AREA(a, b) 将扩展成c/a * b , c 与b 本应该是除法运算,结果变成了乘法运算,造成错误。如果定义#define RECTANGLE_AREA(a, b) (a) * (b)密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第29页,共61页Page 29 , Total61则RECTANGLE_AREA(c + d, e + f)将扩展成:(c + d * e + f), d与e 先运算,造成错误。规则5.2 将宏所定义的多条表达式放在大括号中。说明:更好的方法是多条语句写成do while(0)的方式。示例:看下面的语句,只有宏的第一条表达式被执行。#define FOO(x) \printf("arg is %d\n", x); \do_something_useful(x);为了说明问题,下面for语句的书写稍不符规范for (blah = 1; blah & 10; blah++)FOO(blah)用大括号定义的方式可以解决上面的问题:#define FOO(x) { \printf("arg is %s\n", x); \do_something_useful(x); \}但是如果有人这样调用:if (condition == 1)FOO(10);elseFOO(20);那么这个宏还是不能正常使用,所以必须这样定义才能避免各种问题:#define FOO(x) do { \printf("arg is %s\n", x); \do_something_useful(x); \} while(0)用do-while(0)方式定义宏,完全不用担心使用者如何使用宏,也不用给使用者加什么约束。规则5.3 使用宏时,不允许参数发生变化。示例:如下用法可能导致错误。#define SQUARE(a) ((a) * (a))int a = 5;b = SQUARE(a++); // 结果:a = 7,即执行了两次增。正确的用法是:b = SQUARE(a);a++; // 结果:a = 6,即只执行了一次增。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第30页,共61页Page 30 , Total61同时也建议即使函数调用,也不要在参数中做变量变化操作,因为可能引用的接口函数,在某个版本升级后,变成了一个兼容老版本所做的一个宏,结果可能不可预知。规则5.4 不允许直接使用魔鬼数字。说明:使用魔鬼数字的弊端:代码难以理解;如果一个有含义的数字多处使用,一旦需要修改这个数值,代价惨重。使用明确的物理状态或物理意义的名称能增加信息,并能提供单一的维护点。解决途径:对于局部使用的唯一含义的魔鬼数字,可以在代码周围增加说明注释,也可以定义局部const变量,变量命名自注释。对于广泛使用的数字,必须定义const全局变量/宏;同样变量/宏命名应是自注释的。0作为一个特殊的数字,作为一般默认值使用没有歧义时,不用特别定义。建议5.1 除非必要,应尽可能使用函数代替宏。说明:宏对比函数,有一些明显的缺点:宏缺乏类型检查,不如函数调用检查严格。宏展开可能会产生意想不到的副作用,如#define SQUARE(a) (a) * (a)这样的定义,如果是SQUARE(i++),就会导致i被加两次;如果是函数调用double square(double a) {return a *}则不会有此副作用。以宏形式写的代码难以调试难以打断点,不利于定位问题。宏如果调用的很多,会造成代码空间的浪费,不如函数空间效率高。示例:下面的代码无法得到想要的结果:#define MAX_MACRO(a, b) ((a) & (b) ? (a) : (b))int MAX_FUNC(int a, int b) {return ((a) & (b) ? (a) : (b));}int testFunc(){unsigned int a = 1;int b = -1;printf("MACRO: max of a and b is: %d\n", MAX_MACRO(++a, b));printf("FUNC : max of a and b is: %d\n", MAX_FUNC(a, b));return 0;}上面宏代码调用中,结果是(a & b),所以a只加了一次,所以最终的输出结果是:MACRO: max of a and b is: -1FUNC : max of a and b is: 2建议5.2 常量建议使用const定义代替宏。说明: &尽量用编译器而不用预处理&,因为#define经常被认为好象不是语言本身的一部分。看下面的语句:#define ASPECT_RATIO 1.653密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第31页,共61页Page 31 , Total61编译器会永远也看不到ASPECT_RATIO这个符号名,因为在源码进入编译器之前,它会被预处理程序去掉,于是ASPECT_RATIO不会加入到符号列表中。如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指的是1.653,而不是ASPECT_RATIO。如果ASPECT_RATIO不是在你自己写的头文件中定义的,你就会奇怪1.653是从哪里来的,甚至会花时间跟踪下去。这个问题也会出现在符号调试器中,因为同样地,你所写的符号名不会出现在符号列表中。解决这个问题的方案很简单:不用预处理宏,定义一个常量:const double ASPECT_RATIO = 1.653;这种方法很有效,但有两个特殊情况要注意。首先,定义指针常量时会有点不同。因为常量定义一般是放在头文件中(许多源文件会包含它),除了指针所指的类型要定义成const外,重要的是指针也经常要定义成const。例如,要在头文件中定义一个基于char*的字符串常量,你要写两次const:const char * const authorName = "Scott Meyers";延伸阅读材料:关于const和指针的使用,这里摘录两段ISO/IEC 9899(俗称C99)的描述:The following pair of declarations demonstrates the difference between a "variable pointer to a constant value" and a "constant pointer to a variable value".const int *ptr_to_int *const constant_The contents of any object pointed to by ptr_to_constant shall not be modified through that pointer,but ptr_to_constant itself may be changed to point to another object. Similarly, the contents of the intpointed to by constant_ptrmay be modified, but constant_ptritself shall always point to the same location.The declaration of the constant pointer constant_ptr may be clarified by including a definition for the type "pointer to int".typedef int *int_const int_ptr constant_declares constant_ptras an object that has type "const-qualified pointer to int".建议5.3 宏定义中尽量不使用return、goto、continue、break等改变程序流程的语句。说明:如果在宏定义中使用这些改变流程的语句,很容易引起资源泄漏问题,使用者很难自己察觉。示例:在某头文件中定义宏CHECK_AND_RETURN:#define CHECK_AND_RETURN(cond, ret) {if (cond == NULL_PTR) {}}然后在某函数中使用(只说明问题,代码并不完整):pMem1 = VOS_MemAlloc(...);CHECK_AND_RETURN(pMem1 , ERR_CODE_XXX)pMem2 = VOS_MemAlloc(...);CHECK_AND_RETURN(pMem2 , ERR_CODE_XXX) /*此时如果pMem2==NULL_PTR,则pMem1未释放函数就返回了,造成内存泄漏。*/所以说,类似于CHECK_AND_RETURN这些宏,虽然能使代码简洁,但是隐患很大,使用须谨慎。密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第32页,共61页Page 32 , Total616 质量保证原则6.1 代码质量保证优先原则(1)正确性,指程序要实现设计要求的功能。(2)简洁性,指程序易于理解并且易于实现。(3)可维护性,指程序被修改的能力,包括纠错、改进、新需求或功能规格变化的适应能力。(4)可靠性,指程序在给定时间间隔和环境条件下,按设计要求成功运行程序的概率。(5)代码可测试性,指软件发现故障并隔离、定位故障的能力,以及在一定的时间和成本前提下,进行测试设计、测试执行的能力。(6)代码性能高效,指是尽可能少地占用系统资源,包括内存和执行时间。(7)可移植性,指为了在原来设计的特定环境之外运行,对系统进行修改的能力。(8)个人表达方式/个人方便性,指个人编程习惯。原则6.2 要时刻注意易混淆的操作符。说明:包括易混淆和的易用错操作符1、易混淆的操作符C语言中有些操作符很容易混淆,编码时要非常小心。赋值操作符&=& 逻辑操作符&==&关系操作符&&& 位操作符"&&"关系操作符&&& 位操作符&&&&逻辑操作符&||& 位操作符"|"逻辑操作符&&&& 位操作符"&"逻辑操作符"!" 位操作符&~&2、易用错的操作符(1) 除操作符"/"当除操作符&/&的运算量是整型量时,运算结果也是整型。如:1/2=0(2)求余操作符"%"求余操作符"%"的运算量只能是整型。如:5%2=1,而5.0%2是错误的。(3)自加、自减操作符&++&、&--&示例1k = 5;x = k++;执行后,x = 5,k = 6示例2k = 5;x = ++k;执行后,x = 6,k = 6示例3密级:confidentiality levelDKBA
华为机密,未经许可不得扩散 Huawei Confidential 第33页,共61页Page 33 , Total61k = 5;x = k--;执行后,x = 5,k = 4示例4k = 5;x = --k;执行后,x = 4,k = 4原则6.3 必须了解编译系统的内存分配方式,特别是编译系统对不同类型的变量的内存分配规则,如局部变量在何处分配、静态变量在何处分配等。原则6.4 不仅关注接口,同样要关注实现。说明:这个原则看似和&面向接口&编程思想相悖,但是实现往往会影响接口,函数所能实现的功能,除了和调用者传递的参数相关,往往还受制于其他隐含约束,如:物理内存的限制,网络状况,具体看&抽象漏洞原则&。延伸阅读材料: http://local.joelonsoftware.com/mediawiki/index.php?title=Chinese_%28Simplified%29&oldid=9699规则6.1 禁止内存操作越界。说明:内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。示例:使用itoa()将整型数转换为字符串时:char TempShold[10] ;itoa(ProcFrecy,TempShold, 10); /* 数据库刷新间隔设为值时,系统监控后台coredump,监控前台抛异常。*/TempShold是以&\0&结尾的字符数组,只能存储9个字符,而ProcFrecy的最大值可达到10位,导致符数组TempShold越界。正确写法:一个int(32位)在-~之间,将数组TempShold设置成12位。char TempShold[

我要回帖

更多关于 华为y635 cl00 的文章

 

随机推荐