Identifiers (variable names, labels, structure tags, derived macro names, etc.) may be an arbitrary length. The ISO standard only guarantees that language processors only pay attention to the first 31 symbols when comparing identifiers. Note that the same ISO standard requires that external labels (those visible to the linker) be unique in their first six characters. Since it has been confirmed that 31 character / case significance is supported by EDK II supported tool chains, there is no requirement to ensure uniqueness of externals within the first 6 characters.
While not as big an issue as it has been in the past, when choosing labels ensure that the label is unlikely to be confused with other labels used in the file. Ensure that long label names vary by more than one or two characters. Ensure that labels don't vary between zero and oh (0 and O), one and ell (1 and l). Some also consider 2 and Z, and 5 and S to be similar.
This set of detailed guidelines for naming variables and routines is a convention widely used with the C programming language, especially in Microsoft* Windows* programming. An example of a non-compliant variable named with the Hungarian conventions follows:
bmRequestType; // Byte mask, First byte in the USB message header
pachInsert; // A pointer to an array of characters to insert.
Global data and module data shall be prefixed with 'g' or 'm', respectively. Pointer variables may optionally be prefixed with 'p'. These are the only exceptions to the prohibition against Hungarian notation.
There are no exceptions to this rule. The 'm
' prefix identifies a variable
with module scope, while a 'g
' prefix identifies a global variable.
gThisIsAGlobalVariableName
mThisIsAModuleVariableName
Time has shown that pass-by-value vs. pass-by-reference errors are
significantly reduced with only the introduction of a 'p
' prefix for pointer
variables.
The abstraction of abstract data types is ignored. Instead, base types based on programminglanguage integers or long integers are abstracted. Thus, the names are focused on data types instead of the object-oriented abstraction that they represent. This focus is of little value and forces manual type checking that can be accomplished easily by the compiler with warnings promoted to errors.
Hungarian notation combines data meaning with data representation. If you change a data type you have to rename the variable. There is no mechanism to ensure that the names are accurate.
Studies have shown that Hungarian notation tends to encourage lazy variable names. It's common to focus on the Hungarian prefix without putting effort into a descriptive name.
Use of all upper- or all lower-case is very difficult to read because compound words cannot be clearly separated.
4.4.4.2 The names of newly created global entities (such as structures, macros, and defines) shall not use an EFI_
prefix.
From now on, the use of DXE_
and PEI_
prefixes shall be reserved for DXE and
PEI drivers, respectively. If a structure happens to apply equally to PEI and
DXE, it should use the prefix DXE_
. If a structure is local to a particular
module only, no special prefix is required.
When all letters in an acronym are capitalized, it makes the prior and subsequent words visually difficult to distinguish.
ThisIsAnExampleOfWhatToDoForPci
4.4.4.4 Never use C keywords or the names of symbols declared in the standard header files as internal symbols.
When you need to use the name of an existing library function for a user-defined function, each use of the user-defined function must be paired with a corresponding comment. The ISO standard does not, however, guarantee that the user-defined function will take priority over the library function.
In principle, the ISO standard, reserves all names beginning with underscore + capital letter, or with underscore + underscore. External symbols names shall not begin with an underscore.
auto | break | case | char | const |
continue | default | do | double1 | else |
enum | extern | float1 | for | goto |
if | int | long | register | return |
short | signed | sizeof | static | struct |
switch | typedef | union | unsigned | void |
volatile | while | inline | restrict | wchar_t |
bool | true | false | NULL | _Bool2 |
_Complex2 | _Imaginary2 | and3 | and_eq3 | bitand3 |
bitor3 | compl3 | not3 | not_eq3 | or3 |
or_eq3 | xor3 | xor_eq3 |
In addition to those listed, the identifiers asm and fortran are common language extensions and should also be treated as reserved.
This clearly differentiates static declarations from dynamic data types.
The underscore effectively separates the words, making names more readable.
typedef UINT32 THIS_IS_AN_EXAMPLE_OF_WHAT_TO_DO_FOR_PCI;
The guard macro, used in the #ifndef
at the start of an include file, uses a
postfix underscore character '_
', in its name in order to prevent collision
with other names that follow the naming convention. This may not be sufficient
for header files that don't have a unique name. In that case, additional text
may have to be added to the macro name in order to make it unique. This may not
be required if the header files are mutually exclusive.
#ifndef FILE_NAME_H_
#define FILE_NAME_H_
...
#if (A_NUMBER > 72)
...
#else // NOT (A_NUMBER > 72)
...
#endif // (A_NUMBER > 72)
...
#endif /* FILE_NAME_H_ */
4.4.5.5 The #else and #endif clauses of conditional compilation blocks shall be commented to identify their context.
If a conditional compilation construct spans more than seven lines, a comment
shall be added to the construct's #else
and #endif
clauses identifying the
block the clause is associated with. This is illustrated in the preceding code
example. The comment shall be on the same line as the #else
or #endif
clause.