# å†…æ ¸ç¼–ç 规范 æ¤è§„范基于业界通用的编程规范整ç†è€Œæˆï¼Œè¯·å†…æ ¸çš„å¼€å‘人员éµå®ˆè¿™æ ·çš„ç¼–ç¨‹é£Žæ ¼ã€‚ ## 总体原则 总体原则: - 清晰:代ç 应当易于ç†è§£ã€æ˜“äºŽç»´æŠ¤ã€æ˜“äºŽé‡æž„,é¿å…æ™¦æ¶©è¯æ³• - 简æ´ï¼šå‘½å简çŸï¼Œå‡½æ•°ç´§å‡‘ - 高效:通过使用算法ã€ç¼–è¯‘å™¨ä¼˜åŒ–é€‰é¡¹æˆ–ç¡¬ä»¶èµ„æºæé«˜ç¨‹åºæ•ˆçއ - 美观:代ç é£Žæ ¼åˆç†ã€ä¸€è‡´ 在大部分情况下,开å‘人员应当éµä»Žä»¥ä¸‹è§„范,但也有一些例外场景。如修改第三方开æºä»£ç 或大é‡ä½¿ç”¨å¼€æºä»£ç 接å£ä¸‹ï¼Œåº”当与开æºä»£ç ä¿æŒä¸€è‡´ã€‚è¯·ä¾æ®æ€»ä½“åŽŸåˆ™ï¼Œçµæ´»å¤„ç†ã€‚ ## 目录结构 建议按照功能模å—划分å目录,å目录å†å®šä¹‰å¤´æ–‡ä»¶å’Œæºæ–‡ä»¶ç›®å½•。 目录å和文件å如果没有特殊的需è¦ï¼Œé‡‡ç”¨å…¨å°å†™çš„å½¢å¼ï¼Œå¯ä»¥ä½¿ç”¨ä¸‹åˆ’线(“_â€ï¼‰åˆ†å‰²ã€‚ ## å‘½å æŽ¨èä½¿ç”¨é©¼å³°é£Žæ ¼ï¼Œå…·ä½“è§„åˆ™å¦‚ä¸‹ï¼š | 类型 | 命åé£Žæ ¼ | å½¢å¼ | | -------- | -------- | -------- | | 函数ã€ç»“æž„ä½“ç±»åž‹ã€æžšä¸¾ç±»åž‹ã€è”åˆä½“类型ã€typedef的类型 | 大驼峰,或带有模å—å‰ç¼€çš„大驼峰 | AaaBbb<br/>XXX_AaaBbb | | 局部å˜é‡ï¼Œå‡½æ•°å‚数,å®å‚数,结构体ä¸å—段,è”åˆä½“䏿ˆå‘˜ | å°é©¼å³° | aaaBBB | | 全局å˜é‡ | 带“g_â€å‰ç¼€çš„å°é©¼å³° | g_aaaBBB | | å®ï¼ˆä¸å«å‡½æ•°å¼å®ï¼‰ï¼Œæžšä¸¾å€¼ï¼Œgotoæ ‡ç¾ | 全大写,下划线分割 | AAA_BBB | | 函数å¼å® | 全大写下划线分割,或大驼峰,或带有模å—å‰ç¼€çš„大驼峰 | AAA_BBB<br/>AaaBbb<br/>XXX_AaaBbb | | 头文件防æ¢é‡å¤çš„ç¬¦å· | 以下划线“_â€å¼€å¤´ä»¥H结尾,ä¸é—´ä¸ºæ–‡ä»¶å的全大写并以下划线分割 | _AAA_H | å†…æ ¸å¯¹å¤–API建议采用LOS_ModuleFunc的形å¼ï¼Œå¦‚果有宾è¯åˆ™å»ºè®®é‡‡ç”¨å‰ç½®çš„æ–¹å¼ï¼Œæ¯”如: ``` LOS_TaskCreate LOS_MuxLock ``` kernel目录下内部模å—间的接å£ä½¿ç”¨OsModuleFunc的形å¼ï¼Œæ¯”如: ``` OsTaskScan OsMuxInit ``` ## 注释 一般的,尽é‡é€šè¿‡æ¸…晰的软件架构,良好的符å·å‘½åæ¥æé«˜ä»£ç å¯è¯»æ€§ï¼›åœ¨éœ€è¦çš„æ—¶å€™ï¼Œè¾…以注释说明。 注释是为了帮助阅读者快速读懂代ç ,所以è¦ä»Žè¯»è€…的角度出å‘,按需注释。 注释内容è¦ç®€æ´ã€æ˜Žäº†ã€æ— æ§ä¹‰ï¼Œä¿¡æ¯å…¨é¢ä¸”ä¸å†—余。 文件头部è¦è¿›è¡Œæ³¨é‡Šï¼Œå»ºè®®æ³¨é‡Šåˆ—出:版æƒè¯´æ˜Žã€æ–‡ä»¶åŠŸèƒ½è¯´æ˜Žï¼Œä½œè€…ã€åˆ›å»ºæ—¥æœŸã€æ³¨æ„事项ç‰ã€‚ æ³¨é‡Šé£Žæ ¼è¦ç»Ÿä¸€ï¼Œå»ºè®®ä¼˜å…ˆé€‰æ‹©/\* \*/的方å¼ï¼Œæ³¨é‡Šç¬¦ä¸Žæ³¨é‡Šå†…å®¹ä¹‹é—´è¦æœ‰1ç©ºæ ¼ï¼Œå•行ã€å¤šè¡Œæ³¨é‡Šé£Žæ ¼å¦‚下: ``` /* å•行注释 */ // å•行注释 /* * 多行注释 * 第二行 */ // 多行注释 // å¦ä¸€è¡Œ ``` 针对代ç 的注释,应该置于对应代ç çš„ä¸Šæ–¹æˆ–å³æ–¹ã€‚ 代ç 上方的注释,与代ç è¡Œé—´æ— ç©ºè¡Œï¼Œä¿æŒä¸Žä»£ç ä¸€æ ·çš„ç¼©è¿›ã€‚ 代ç å³è¾¹çš„æ³¨é‡Šï¼Œä¸Žä»£ç 之间,至少留1ç©ºæ ¼ã€‚ 建议将多æ¡è¿žç»çš„å³ä¾§æ³¨é‡Šå¯¹é½ï¼Œæ¯”如: ``` #define CONST_A 100 /* Const A */ #define CONST_B 2000 /* Const B */ ``` ## æ ¼å¼ ç¨‹åºé‡‡ç”¨ç¼©è¿›é£Žæ ¼ç¼–å†™ï¼Œä½¿ç”¨ç©ºæ ¼è€Œä¸æ˜¯åˆ¶è¡¨ç¬¦ï¼ˆâ€™\t’)进行缩进,æ¯çº§ç¼©è¿›ä¸º4ä¸ªç©ºæ ¼ã€‚ æ¢è¡Œæ—¶ï¼Œå‡½æ•°å·¦å¤§æ‹¬å·å¦èµ·ä¸€è¡Œæ”¾è¡Œé¦–,并独å 一行;其他左大括å·è·Ÿéšè¯å¥æ”¾è¡Œæœ«ã€‚å³å¤§æ‹¬å·ç‹¬å 一行,除éžåŽé¢è·Ÿç€åŒä¸€è¯å¥çš„剩余部分,如 do è¯å¥ä¸çš„ while,或者 if è¯å¥çš„else/else if,或者逗å·ã€åˆ†å·ã€‚ 一行åªå†™ä¸€æ¡è¯å¥ã€‚ 比如: ``` struct MyType { // è·Ÿéšè¯å¥æ”¾è¡Œæœ«ï¼Œå‰ç½®1ç©ºæ ¼ ... }; // å³å¤§æ‹¬å·åŽé¢ç´§è·Ÿåˆ†å· int Foo(int a) { // 函数左大括å·ç‹¬å 一行,放行首 if (a > 0) { Foo(); // ä¸€è¡Œåªæœ‰ä¸€æ¡è¯å¥ Bar(); } else { // å³å¤§æ‹¬å·ã€"else"ã€ä»¥åŠåŽç»çš„左大括å·å‡åœ¨åŒä¸€è¡Œ ... } // å³å¤§æ‹¬å·ç‹¬å 一行 ... } ``` æ¯è¡Œå—符数ä¸è¦è¶…过 120 个,代ç 过长时应当æ¢è¡Œï¼Œæ¢è¡Œæ—¶å°†æ“作符留在行末,新行缩进一层或进行åŒç±»å¯¹é½ï¼Œå¹¶å°†è¡¨ç¤ºæœªç»“æŸçš„æ“ä½œç¬¦æˆ–è¿žæŽ¥ç¬¦å·ç•™åœ¨è¡Œæœ«ã€‚ ``` // å‡è®¾ä¸‹é¢ç¬¬ä¸€è¡Œå·²ç»ä¸æ»¡è¶³è¡Œå®½è¦æ±‚ if (currentValue > MIN && // Good:æ¢è¡ŒåŽï¼Œå¸ƒå°”æ“作符放在行末 currentValue < MAX) { // Good: 与(&&)æ“作符的两个æ“作数åŒç±»å¯¹é½ DoSomething(); ... } flashPara.flashEndAddr = flashPara.flashBaseAddr + // Good: åŠ å·ç•™åœ¨è¡Œæœ« flashPara.flashSize; // Good: åŠ æ³•ä¸¤ä¸ªæ“ä½œæ•°å¯¹é½ // Goodï¼šå‡½æ•°å‚æ•°æ”¾åœ¨ä¸€è¡Œ ReturnType result = FunctionName(paramName1, paramName2); ReturnType result = FunctionName(paramName1, paramName2, paramName3); // Goodï¼šä¿æŒä¸Žä¸Šæ–¹å‚æ•°å¯¹é½ ReturnType result = FunctionName(paramName1, paramName2, paramName3, paramName4, paramName5); // Goodï¼šå‚æ•°æ¢è¡Œï¼Œ4 ç©ºæ ¼ç¼©è¿› ReturnType result = VeryVeryVeryLongFunctionName( // è¡Œå®½ä¸æ»¡è¶³ç¬¬1ä¸ªå‚æ•°ï¼Œç›´æŽ¥æ¢è¡Œ paramName1, paramName2, paramName3); // æ¢è¡ŒåŽï¼Œ4 ç©ºæ ¼ç¼©è¿› // Good:æ¯è¡Œçš„傿•°ä»£è¡¨ä¸€ç»„相关性较强的数æ®ç»“构,放在一行便于ç†è§£ int result = DealWithStructLikeParams(left.x, left.y, // è¡¨ç¤ºä¸€ç»„ç›¸å…³å‚æ•° right.x, right.y); // 表示å¦å¤–ä¸€ç»„ç›¸å…³å‚æ•° ``` 包括 if/for/while/do-while è¯å¥åº”使用大括å·ï¼Œå³å¤åˆè¯å¥ã€‚ ``` while (condition) {} // Good:å³ä½¿å¾ªçŽ¯ä½“æ˜¯ç©ºï¼Œä¹Ÿåº”ä½¿ç”¨å¤§æ‹¬å· while (condition) { continue; // Good:continue è¡¨ç¤ºç©ºé€»è¾‘ï¼Œä½¿ç”¨å¤§æ‹¬å· } ``` case/default è¯å¥ç›¸å¯¹ switch ç¼©è¿›ä¸€å±‚ï¼Œé£Žæ ¼å¦‚ä¸‹ï¼š ``` switch (var) { case 0: // Good: 缩进 DoSomething1(); // Good: 缩进 break; case 1: { // Good: å¸¦å¤§æ‹¬å·æ ¼å¼ DoSomething2(); break; } default: break; } ``` 指针类型"\*"è·Ÿéšå˜é‡æˆ–者函数å,例如: ``` int *p1; // OK int* p2; // Bad:跟éšç±»åž‹ int*p3; // Badï¼šä¸¤è¾¹éƒ½æ²¡ç©ºæ ¼ int * p4; // Badï¼šä¸¤è¾¹éƒ½æœ‰ç©ºæ ¼ struct Foo *CreateFoo(void); // OK: "*"è·Ÿéšå‡½æ•°å 特例: char * const VERSION = "V100"; // OK: 当有 const 修饰符时,"*"ä¸¤è¾¹éƒ½æœ‰ç©ºæ ¼ int Foo(const char * restrict p); // OK: 当有 restrict 修饰符时,"*"ä¸¤è¾¹éƒ½æœ‰ç©ºæ ¼ sz = sizeof(int*); // OK:å³ä¾§æ²¡æœ‰å˜é‡ï¼Œ"*"è·Ÿéšç±»åž‹ ``` ## å® å®šä¹‰å‡½æ•°å¼å®å‰ï¼Œåº”考虑能å¦ç”¨å‡½æ•°æ›¿ä»£ã€‚å¯¹äºŽå¯æ›¿ä»£åœºæ™¯ï¼Œå»ºè®®ç”¨å‡½æ•°æ›¿ä»£å®ã€‚对于有性能需求的场景,å¯ä»¥ä½¿ç”¨å†…è”函数。 å®šä¹‰å®æ—¶ï¼Œè¦ä½¿ç”¨å®Œå¤‡çš„æ‹¬å·ï¼Œä¾‹å¦‚: ``` #define SUM(a, b) ((a) + (b)) // ç¬¦åˆæœ¬è§„èŒƒè¦æ±‚. #define SOME_CONST 100 // Good: å•ç‹¬çš„æ•°å—æ— éœ€æ‹¬å· #define ANOTHER_CONST (-1) // Good: 负数需è¦ä½¿ç”¨æ‹¬å· #define THE_CONST SOME_CONST // Good: å•ç‹¬çš„æ ‡è¯†ç¬¦æ— éœ€æ‹¬å· ``` ä»¥ä¸‹æƒ…å†µéœ€è¦æ³¨æ„: - å®å‚æ•°å‚与 '\#', '\#\#' æ“作时,ä¸è¦åŠ æ‹¬å·ï¼› - å®å‚æ•°å‚与å—符串拼接时,ä¸è¦åŠ æ‹¬å·ï¼› - å®å‚数作为独立部分,在赋值(包括+=, -=ç‰ï¼‰æ“作的æŸä¸€è¾¹æ—¶ï¼Œå¯ä»¥ä¸åŠ æ‹¬å·ï¼› - å®å‚数作为独立部分,在逗å·è¡¨è¾¾å¼ï¼Œå‡½æ•°æˆ–å®è°ƒç”¨åˆ—表ä¸ï¼Œå¯ä»¥ä¸åŠ æ‹¬å·ã€‚ ``` // x ä¸è¦åŠ æ‹¬å· #define MAKE_STR(x) #x // obj ä¸è¦åŠ æ‹¬å· #define HELLO_STR(obj) "Hello, " obj // a, b éœ€è¦æ‹¬å·ï¼›è€Œ value å¯ä»¥ä¸åŠ æ‹¬å· #define UPDATE_VALUE(value, a, b) (value = (a) + (b)) // a éœ€è¦æ‹¬å·ï¼›è€Œ b å¯ä»¥ä¸åŠ æ‹¬å· #define FOO(a, b) Bar((a) + 1, b) ``` 包å«å¤šæ¡è¯å¥çš„函数å¼å®çš„实现è¯å¥å¿…须放在 do-while(0)ä¸ã€‚ ç¦æ¢æŠŠå¸¦å‰¯ä½œç”¨çš„表达å¼ä½œä¸ºå‚æ•°ä¼ é€’ç»™å‡½æ•°å¼å®ï¼Œæ¯”å¦‚è‡ªåŠ æ“作(“a++â€)。 函数å¼å®å®šä¹‰ä¸æ…Žç”¨ returnã€gotoã€continueã€break ç‰æ”¹å˜ç¨‹åºæµç¨‹çš„è¯å¥ã€‚ ç¦æ¢å®è°ƒç”¨å‚æ•°ä¸å‡ºçŽ°é¢„ç¼–è¯‘æŒ‡ä»¤ï¼Œå¦‚\#include,\#deï¬neå’Œ\#ifdefï¼Œè¿™æ ·åšä¼šå¯¼è‡´æœªå®šä¹‰çš„行为。 å®å®šä¹‰ä¸ä»¥åˆ†å·ç»“尾。 ## 头文件 头文件应当èŒè´£å•一。 通常情况下,æ¯ä¸ª.c文件都应有一个相应的.h文件(并ä¸ä¸€å®šåŒå),用于放置对外æä¾›çš„函数声明ã€å®å®šä¹‰ã€ç±»åž‹å®šä¹‰ç‰ã€‚如果ä¸éœ€è¦æä¾›å¯¹å¤–接å£ï¼Œå¯ä»¥æ²¡æœ‰å¯¹åº”çš„.h文件。 é¿å…头文件循环ä¾èµ–,如a.h åŒ…å« b.h,b.h åŒ…å« c.h,c.h åŒ…å« a.h。 头文件应当自包å«ï¼Œå³åŒ…嫿Ÿä¸ªå¤´æ–‡ä»¶ï¼Œä¸éœ€è¦å¼•入其他头文件就å¯ä»¥ç¼–译。 头文件用\#deï¬neã€\#ifndefã€\#endifä¿æŠ¤ï¼Œé˜²æ¢é‡å¤åŒ…å«ï¼›ä¸è¦ä½¿ç”¨ \#pragma once。 ç¦æ¢é€šè¿‡å£°æ˜Žçš„æ–¹å¼å¼•用外部函数接å£ã€å˜é‡ï¼Œåªèƒ½é€šè¿‡åŒ…å«å¤´æ–‡ä»¶çš„æ–¹å¼ä½¿ç”¨å…¶ä»–æ¨¡å—æˆ–文件æä¾›çš„æŽ¥å£ã€‚ 建议按稳定度包å«å¤´æ–‡ä»¶ï¼Œä¾æ¬¡é¡ºåºä¸ºï¼š æºç 对应的头文件,Cæ ‡å‡†åº“ï¼Œæ“作系统库,平å°åº“,项目公共库,自己其他的ä¾èµ–。 ## æ•°æ®ç±»åž‹ 基础数æ®ç±»åž‹å»ºè®®ä½¿ç”¨los_compiler.hä¸å®šä¹‰çš„ç±»åž‹ï¼Œæ¯”å¦‚æ— ç¬¦å·32使•´æ•°ä½å®šä¹‰ä¸ºUINT32。 ## å˜é‡ é¿å…大釿 ˆåˆ†é…,如较大的局部数组。 谨慎使用全局å˜é‡ï¼Œå°½é‡ä¸ç”¨æˆ–少用全局å˜é‡ã€‚ å˜é‡åº”当åˆå§‹åŒ–åŽå†ä½¿ç”¨ã€‚ ç¦æ¢å°†å±€éƒ¨å˜é‡çš„地å€è¿”回到其作用域以外。 指å‘资æºå¥æŸ„或æè¿°ç¬¦çš„å˜é‡ï¼Œåœ¨èµ„æºé‡Šæ”¾åŽç«‹å³èµ‹äºˆæ–°å€¼ï¼ˆå¦‚æžœå˜é‡çš„作用域马上结æŸå¯ä»¥ä¸èµ‹äºˆæ–°å€¼ï¼‰ã€‚指å‘资æºå¥æŸ„或æè¿°ç¬¦çš„å˜é‡åŒ…æ‹¬æŒ‡é’ˆã€æ–‡ä»¶æè¿°ç¬¦ã€socketæè¿°ç¬¦ä»¥åŠå…¶å®ƒæŒ‡å‘资æºçš„å˜é‡ã€‚ ## æ–言 æ–言必须使用å®å®šä¹‰ï¼Œä¸”åªèƒ½åœ¨è°ƒè¯•版本ä¸ç”Ÿæ•ˆã€‚ æ–言应当看作设计约æŸï¼Œç¦æ¢ç”¨æ–言检测程åºåœ¨è¿è¡ŒæœŸé—´å¯èƒ½å¯¼è‡´çš„错误,å¯èƒ½å‘生的错误è¦ç”¨é”™è¯¯å¤„ç†ä»£ç æ¥å¤„ç†ã€‚ ç¦æ¢åœ¨æ–言内改å˜è¿è¡ŒçŽ¯å¢ƒã€‚ 一个æ–言åªç”¨äºŽæ£€æŸ¥ä¸€ä¸ªé”™è¯¯ã€‚ ## 函数 由一个进程å‘å¦ä¸€ä¸ªè¿›ç¨‹å‘é€çš„æ•°æ®ã€ç”±åº”用å‘å†…æ ¸å‘é€çš„æ•°æ®ç‰åº”å½“è¿›è¡Œåˆæ³•æ€§æ ¡éªŒï¼Œæ ¡éªŒåŒ…æ‹¬ä½†ä¸é™äºŽï¼š - æ ¡éªŒæ•°æ®é•¿åº¦ - æ ¡éªŒæ•°æ®èŒƒå›´ - æ ¡éªŒæ•°æ®ç±»åž‹å’Œæ ¼å¼ - æ ¡éªŒè¾“å…¥åªåŒ…å«å¯æŽ¥å—çš„å—符(“白åå•â€å½¢å¼ï¼‰ 函数应é¿å…使用全局å˜é‡ã€é™æ€å±€éƒ¨å˜é‡å’Œç›´æŽ¥çš„I/Oæ“作,ä¸å¯é¿å…时,应当对读写æ“作进行å°è£…。