我最开始当程序员用C语言写代码,公司里推行编码规范,变量的前缀都是有规定的。
比如整型变量,前面都是 u8Name, i8Name, u16Name, i16Name之类的。
尤其是嵌入式编程,涉及到代码移植的问题,最好使用和平台无关的类型定义。
而且在团队合作中,大家一起编码,如果不遵循统一的编码规范,会造成代码的混乱,降低可理解和可维护性。
但实际操作起来,需要一定的成本,要团队每个人都养成习惯,着实不容易。
因为众口难调,每个人对编码规范中的命名原则的理解程度、认可程度都不同。按着规则来给变量函数等命名,增加了编码的成本,降低了效率,而且名字会显得怪怪的,也不好看。从其他角度看,项目人员流动大、日程紧、跨地域团队合作等因素,也都影响着编码规范的推行。
可存在即合理,在崇尚自由和风格的时代,程序员也有自由发挥的权利,找一套自己喜欢的编码风格,作为自己出产代码的标签,也没什么不好。
毕竟现在编程辅助工具也多,可以更好的减少因命名产生的缺点,比如代码静态检查、语法高亮显示、编码时自动补全等功能。
下面是我整理的,关于变量命名的前缀的一些看法:
前缀 Prefix | 含义 Description |
obj | 一个类对象 |
stt | struct结构体 |
vod | void类型 |
str | 字符串, string |
stf | 固定长度字符串,string fixed length |
chr | 字符 |
aut或var | 自动类型 |
int | 整型数值,integer |
unt | 无符号整数,unsigned integer |
uni | 共用体,union |
ril | 浮点数类型,real number |
bln | boolean类型,true or false |
enu | 枚举类型,enumeration |
hdl或ptr | 表示指针类型,handle或pointer。如果加在其他类型前,可以简写为一个字符h或p |
lst | 数组list |
pub或g | 全局变量public |
prv或stc | 静态模块内变量,表示static或private (除了public和private,函数内部的自动变量没有对应前缀) |
ref | C++里的引用型的变量,reference |
ret_ | 函数的返回值,return value。 |
m_ | 类或结构体的成员变量,member |
fnt | 函数指针变量名,function pointer |
flg | 位域类型变量,flag |
cnt | 循环控制变量,整数类型,表示计数count |
ctl | 控件名称,control |
dto | DataObject |
btn | Button |
tbl | 表格型变量,二维表格,table |
idx | Index |
grp | Group |
cmd | Command |
clm | column |
cat | Catalog |
rst | Recordset |
fld | Field |
err | Error |
prp | Property |
cnn | Connection |
tmr | Timer |
txt | Text |
shp | Shape |
scr | Screen |
mnu | Menu |
lbl | Label |
lin | Line |
img | Image |
glb | Global |
fra | Frame |
frm | Form |
drv | Driver |
dir | Directory |
dat | Data |
clp | Clipboard |
chk | CheckBox |
app | Application |
sng | Single |
mem | Memory |
lng | Long |
bin | Bianary |
wrk | Work |
usr | User |
doc | Document |
eng | Engine |
dbs | Database |
rpt | report |
opt | Option |
dbl | double |
dec | Decimal |
dtm | Date and time |
cny | Currency |
变量命名举例:
int32_t intLoopCnt;
CPowerManager objPwrMgr;
......
最简单的话,变量名就只用表示其含义的名字即可,第一个字母大写,多个单词的话每个单词的首字母大写,最符合人的阅读习惯。
现在的代码编辑器都很智能,能显示出局部变量、全局变量或静态变量的区别,帮助我们在阅读代码的时候更好的理解。
而使用系统性的变量命名规则,在团队合作、代码维护和个人风格上,会体现一些好处。
或者在逻辑复杂的代码里,提供书写代码时的帮助,以及帮助阅读和理解代码。
如果仅仅几个源文件,每个函数几行代码,数据结构也不复杂,那系统性的变量命名规则就可有可无了。
把代码写出自己的风格,呈现出来的变量名、注释等,都体现了对自己的工作的认真态度。
不管你是写C/C++,Java,VBA还是Python,这些命名规则都可以作为一定的指导。
备注:
1,如果仅使用一个含义的名字,不会引起类型和作用域上的误解,那就不用加这些修饰符,直接首字母大写,起一个表示变量意义的名字即可。
在很多编辑器里,全局变量或静态变量都会有特殊显示格式,如果函数内部定义的变量可以加上“stc”或”stc_“前缀。
2,类的成员变量可以加上"m_" 前缀来区分作用域,其他变量尽量前缀字符不要太多,也不要有下划线。
3,其他的前缀,其实在函数内部的局部变量应用更合适,增加代码可读性和可维护性。
4,一个函数内开头一般都先定义两个变量: int Result; int ret_val;
关于类型名:
1,typedef定义的类型名:
I2C_HandleTypeDef,I2C_Handle_T,或I2C_Handle_Type。
我选择第三种。
2,C++中的Class类型,前缀是C。如果是接口类型的Interface类,则前缀是“I”。
什么是匈牙利命名法
匈牙利命名法(Hungarian notation)是电脑程序设计中的一种变量命名规则。
原始的匈牙利命名法,现在被称为匈牙利应用命名法,由1972年至1981年在施乐帕洛阿尔托研究中心工作的-程序员查尔斯·西蒙尼发明。此人后来成了微软的总设计师。
匈牙利命名法具备语言独立的特性,并且首次在BCPL语言中被大量使用。由于BCPL这种低级语言只有机器码这一种数据内容,因此这种语言本身无法帮助程式设计师来记住变量的类型。匈牙利命名法则通过变量名来帮助程序员记录类型。
在匈牙利命名法中,一个变量名由一个或多个小写字母开始,这些字母有助于记忆变量的类型和用途,紧跟着的就是程序设计师选择的任何名称。这个后半部分的首字母可以大写,以区别前面的类型指示字母(参见驼峰式大小写)。
这种命名法其实是对于西蒙尼祖籍的一种讽刺。匈牙利人名和大多数其他欧洲人名相比是反过来的,即姓氏在名字的前面。举个例子,英语化的名字“Charles Simonyi”在匈牙利语中原本是“Simonyi Károly”。同样的,在匈牙利命名法中,类型名在实际变量名前,而不是像大多数类似Smalltalk编程语言那样,类型放在变量名后,例如firstPoint和lastPoint。后者在西蒙尼任职于施乐帕洛阿尔托研究中心时期非常流行。这种命名法的灵感,可能是受波兰表示法的启发。
此命名法又可细分为:系统匈牙利命名法和匈牙利应用命名法。
在系统匈牙利命名法中,前缀代表了变量的实际数据类型。例如:
* lAccountNum:变量是一个长整数("l");
* arru8NumberList:变量是一个无符号8位整型数组("arru8");
* szName:变量是一个零结束字符串("sz"),这是西蒙尼最开始建议的前缀之一。
匈牙利应用命名法不表示实际数据类型,而是给出了变量目的的提示,或者说它代表了什么。
* rwPosition:变量代表一个行("rw")。
* usName:变量代表一个非安全字符串("us"),需要在使用前处理。
* strName:变量代表一个包含名字的字符串("str")但是没有指明这个字符串是如何实现的。
西蒙尼建议的大多数前缀都是自然语义的,但不是所有。比如下面几个含义是特别的:
* pX是指向另一个X类型的指针,这包含非常少的语义信息。
* d是一个前缀表示两个值的区别,例如,dY可能代表一个图形沿Y轴的距离,而一个仅仅叫做y的变量可能是一个绝对坐标。这完全是自然语义的。
* sz是一个无结束或零结束的字符串。在C中,这包含一些语义信息,因为C语言的char*类型的变量不确定是一个指向单个字符的指针,还是一个字符数组,或是一个零结束字符串。
* w标记一个变量是一个字。这基本上没有包含什么语义信息,因此可以被看作一种系统匈牙利命名法。
* b标记了一个字节,和w对比可能有一些语义信息,因为C语言中,只有char型(以及signed/unsigned char)是一个字节长的,这些类型有时候被用来保存数值而字符。这个前缀可以明确某个变量保存的是字符还是数值。
由于这种命名法通常使用小写字母开头用来助记,但是并没有对助记符本身作规定。有几种被广泛使用的习惯(见下面的示例),但是任意字母组合都可以被使用,只要它们在代码主体中保持一致就可以了。
示例
每一项示例的代码块表示实际生产环境代码中可能出现的命名,示例后的两项解释分别为含义以及这一示例的前缀是哪一个英文单词的简写
* bBusy:布尔型 bool
* cApples:项目计数 count
* dwLightYears:双字(系统) doubleword
* fBusy:布尔型或浮点型 false&true或float
* nSize:整型(系统)或计数(应用)nature
* iSize:整型(系统)或索引(应用)int
* fpPrice:浮点数 floatpoint
* dbPi:双精度浮点数(系统) double
* pFoo:指针 point
* rgStudents:数组或范围 range
* szLastName:零结束字符串 ß
* u32Identifier:无符号32位整型(系统) unsigned32
* stTime:时钟结构 struct
* fnFunction:函数名 function
对于指针和数组来说,它们实际上并不是数据类型,因此通常在助记符后面跟着实际元素的类型。
* pszOwner:指向零结束字符串的指针
* rgfpBalances:浮点值的数组
尽管匈牙利命名法可以被应用在任何程序设计语言和环境中,由于微软在C语言项目中,特别是在Microsoft Windows里的大量应用,使得匈牙利命名法的应用大量存在于和Windows相关的领域:
* hwndFoo:窗口句柄 handle window
* lpszBar:指向零结束字符串的长指针 longpointß
这种命名法又是在C++中被扩展而包含变量的作用域,由一个下划线隔开:
* g_nWheels:全局命名空间的成员,整型
* m_nWheels:结构体/类成员,整型
匈牙利命名法的优点
支持者声称匈牙利命名法的好处包括:[2]
* 不需要集成开发环境的支持,从名字中就可以看出变量的类型
* 拥有类似语义的多个变量可以在一个代码块中使用:dwWidth,iWidth,fWidth,dWidth
* 变量名在仅仅知道他们的类型时可以被轻易记住
* 可以使变量名更加一致
* 决定一个变量名的时候可以更机械化,更快
* 不合适的类型转换和操作可以在阅读代码的时候被检测出来,而不需要编译器的检测
* 在那些数字被当作字符串处理的基于字符串的语言中非常有用(例如Tcl)
* 在匈牙利应用命名法中,变量名确保不会犯以下错误:
heightWindow = window.getWidth()
* 在使用动态类型语言或完全无类型的语言编程时,关于类型的修饰可以更简化。这种语言一般不包含类型修饰(或者可选),因此唯一可以看出哪些类型是被允许的只有名字本身、文档以及通过阅读代码来明白它们在做什么。在这些语言中,包含对于变量类型的指示可能会有助于程序员。就像上面提到的,匈牙利命名法扩展了这样的语言(BCPL)。
* 在包含许多全局对象的复杂程序中(VB/Delphi Forms),拥有一个基本的前缀命名法可以简化在编辑器中查找组件的工作。按btn<Ctrl-Space>可以使编辑器弹出一个Button对象的列表。
匈牙利命名法的缺点
批评者认为:
* 匈牙利命名法在编译器做类型检查时是多余的。一个提供类型检查的语言在确定一个变量与其类型一致时,比人眼仅仅检查变量的用法与变量名一致要强大的多。
* 一些现代的集成开发环境,如Visual Studio在需要时可以显示变量类型,并且自动标记不匹配的类型。使用这种命名法完全没有必要。
* 向标识符添加类型标识导致标识符冗长;同时纵容相同主体名而不同类型的变量导致的歧义,开发人员无法从sWidth、nWidth、fWidth中了解这几个Width的用法区别,更好的写法可能是string input、int width、float zoomedWidth。
* 匈牙利命名法在被用作代表多个属性的时候会造成困惑,如 a_crszkvc30LastNameCol:一个常量引用参数,保存了一个varchar(30)类型的数据库列LastName的内容,而这列又是这个表的主键的一部分。
* 在代码更改后可能造成不一致。如果一个变量的类型改变了,不是变量名的修饰与新的类型不一致,就是变量名必须被改变。
* 由于变量名和类型捆绑在一起,因此不利于代码的移植。一个典型的众所周之的例子就是WPARAM类型,以及在许多Windows系统函数声明中使用的wParam参数。它原本是一个16位的类型,但是在后来的操作系统中被改成了32位或64位,但仍保留原来的名字(它实际的基础类型是UINT_PTR,即一个大小足够保存一个指针的无符号整型)。
* 大多数时候,看到一个变量就意味着知道了它的类型。但是,如果你不知道一个变量是干什么的,知道了它的类型也没什么帮助。
驼峰式大小写
驼峰式大小写(Camel-Case,Camel Case,camel case),计算机程序编写时的一套命名规则(惯例)。
当变数名和函式名称是由二个或多个单字连结在一起,而构成的唯一识别字时,利用“驼峰式大小写”来表示,可以增加变数和函式的可读性。
“驼峰式大小写(Camel-Case)一词来自Perl语言中普遍使用的大小写混合格式,而Larry Wall等人所著的畅销书《Programming Perl》(O'Reilly出版)的封面图片正是一匹骆驼。”
“驼峰式大小写”命名规则可视为一种惯例,并无绝对与强制,为的是增加识别和可读性。一旦选用或设定好命名规则,在程式编写时应保持一致格式。
单字之间不以空格断开(例:camel case)或连接号(-,例:camel-case)、底线(_,例:camel_case)连结,有两种格式:
* 小驼峰式命名法(lower camel case):
第一个单字以小写字母开始;第二个单字的首字母大写,例如:firstName、lastName。 也叫做Dromedary case。
* 大驼峰式命名法(upper camel case):
每一个单字的首字母都采用大写字母,例如:FirstName、LastName、CamelCase,也被称为Pascal命名法(英语:Pascal Case)。
StudlyCaps是指大小写混用且不使用空格、连接号或底线的格式,如sTuDlyCAps,HoTMaiL。StudlyCaps可以视为“驼峰式大小写”的变种。
蛇形命名法
蛇形命名法(snake_case)是指每个空格皆以下划线(_)取代的书写风格,且每个单字的第一个字母皆为小写。蛇形命名法经常被使用在计算机中,例如程式语言的变量名称、函数名字以及文件名称。一份研究指出相较于驼峰式大小写,使用蛇形命名法能够让读者更快速的辨识出其含意。
利用下划线作为分隔符号的使用方法最早可以回朔至1960年代晚期,这种使用方法特别与C语言有关系,在C程式设计语言当中曾出现过,并且与驼峰式大小写形成对比。然而,当时这样的使用方法并没有被特别命名,Python网站也仅仅使用"lower_case_with_underscores"来称呼它。
参考:
https://zh.m.wikipedia.org/zh-hans/%E5%8C%88%E7%89%99%E5%88%A9%E5%91%BD%E5%90%8D%E6%B3%95
https://zh.m.wikipedia.org/zh-hans/%E9%A7%9D%E5%B3%B0%E5%BC%8F%E5%A4%A7%E5%B0%8F%E5%AF%AB
Coding Style Conventions - Win32 apps | Microsoft Learn
RVBA Naming Conventions - Xoc Software (RVBA Conventions, Maya Calendar, et.al.)