编程参考 - 编程中给变量起名时如何选择前缀,以及匈牙利命名法等

我最开始当程序员用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.)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜流冰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值