Detailed info:
Types
Functions
Variables & Function Parameters
Other C language standards' pages:
Abbreviations
C Language Standards
Naming is arguably one of the most important aspects of coding. Good naming conventions have a huge impact on readability, which translates to easier code review and maintenance.
Time spent carefully choosing names or correcting poor naming will almost certainly pay back several times in savings of time and effort in peer reviews, testing, troubleshooting, and renovations (refactoring, re-engineering, design and implementation of new requirements).
The most important requirement for names of identifiers, files, etc. is that they describe what they are. Don't call a pointer to a timer "p", or "tp" (is that toilet paper?). Call it "timerPtr" so at a glance, it's extremely obvious what it is.
It's acceptable for loop counters to be numbered simply "i" (or "j" for a nested loop, or "k" for a nested nested loop), because this is common usage, not only in programming, but also in mathematics.
It's also acceptable for variables with ''very'' limited scope (i.e., limited to a handful of lines of code) to have very simplified names, if that improves readability through reduced clutter. For example, "t" becomes more acceptable for a timer reference if it's used in a tiny code block like this:
Component Interfaces
Module Interfaces
Often, an identifier prefix is needed to prevent naming conflicts between identifiers that are exported to other modules as a part of an interface. Two interfaces may each define a function called "GetSize". To prevent naming conflicts (and avoid programmer confusion), each of those interfaces mut use a unique prefix. Prefixes are also needed for other things besides functions: types, variables, files, and macros.
The structure of an interface-specific prefix differs based on the scope of the interface. The possible scopes are:
Inter-module interfaces are sometimes called intra-component interfaces, but "inter-module" is the preferred term.
Each part of the prefix must start with a lower case letter (unless it is a macro prefix) and must be separated from other parts of the identifier using underscores.
Underscores are used instead of capitalization to separate the parts of the prefix and to separate the prefix from the identifier for several reasons:
Inter-component interfaces have prefixes containing at least two parts:
The company abbreviation indicates the company that owns the interface. For Sierra Wireless, this is usually "swi". For open-source projects, the abbreviation indicates interface's project, like the "Legato" project that starts with le_
.
The interface name abbreviation is simply an abbreviation of the interface's name. A memory management API might have mem
as its abbreviation. This abbreviation should not be longer than 5 characters. Two to four characters is preferred.
A timer API owned by Sierra Wireless might have the prefix swi_tmr_
while the Legato Memory Management API could have the prefix le_mem_
Inter-module interfaces have only one part to their prefix: an interface name abbreviation. A Registration List module could use the prefix rlist_
. A Registration Module that implements the registration objects that get stored in the Registration List might use the prefix reg_:
Because inter-module interfaces are not seen outside of the component where they're defined, it's impossible to have a naming conflict between an inter-module interface in one component and an inter-module interface in another component. Actually, there could still be a conflict at the link stage, if the symbols are allowed to leak out, but a linker script file can be used to prevent this quite easily.
It's also impossible to have a naming conflict between an inter-component interface and an inter-module interface, because all interfaces imported from outside a component will have both a company prefix and an interface name abbreviation. The difference in the prefixes also highlights the scope differences of the identifiers, whichincreases readability.
Like other forms identifiers, the most important requirement for file names is they be descriptive; the name of the file must clearly describe what the file contains.
The files must also be named in a way their names won't conflict with names of other files. This is mainly important for include files. For example, don't call one of your header files "time.h", because that name will conflict with the C standard library file of the same name. That's why inter-component interface headers must be prefixed with the company abbreviation. The Sierra Wireless Transmogrifier"API include file could be named something like swi_transmog.h
. Prefixes aren't required for files only visible within a limited scope (e.g., implementation files or inter-module interfaces only visible inside a single software component).
Macros can be used in similar ways to variables and functions, but their behaviour has subtle differences that can result in bugs or code bloat if used incorrectly. Compiler errors and warnings resulting from macro substitution can also be somewhat cryptic and difficult to understand if it isn't obvious that the code involved is a macro. That's why it's important to easily distinguish a macro from a non-macro when reading code. Macro names must be all uppercase, with words separated using underscores.
Names of macros can also conflict with the names of macros defined in include files from other modules. To reduce the chances of a naming conflict, macros exported to other modules must have a prefix. Even macros only used within a single file should have a prefix if the names are likely to conflict with names defined in standard C libraries or other included code that doesn't use prefixes.
Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.