C Program Style Rules
Alex Dekhtyar (dekhtyar@calpoly.edu)
This document is based, in part, on the C Program Style Rules document,
describing the rules employed by my colleague Dr. Clint Staley. Essentially,
this is a simplified version of those rules with some changes to accommodate the practices I've employed in teaching CSC 101.
0. The Who and Why
Who: These rules are primarily for students taking CSC 101 with me. If you are, then know - any program you submit
will be studied for compliance with these rules. Failure to follow them will yield point deductions. You have been warned!
Why: There are two sets reasons to have code style rules.
- Uniformity. When you work for a software development company, your code is read and worked with by many other people. Because of this, you want to make your code readable. Because there is usually more than one person writing code, you want all code written to be consistent. Style rules set up the guidelines for how the code should look. Knowing what they are and following them allows others
read and understand your code with more ease, and, in turn, allows you to work with other people's code and not be afraid of surprises.
- Convenience. Uniformity, in many cases, just means picking some style, any style, and following it. However, there are some rules
that make sense even in the absense of the need for uniformity. Certain ways to write code are a bad practice and needs to be
prevented regardless of anything else.
1. Identifier names
1.0 Underscores
Do not use underscores in identifier names.
Exception. Often, it may be convenient to use variable names that start with an underscore for debugging purposes.
Use of names such as _x, __flag__, __timeRequired is permitted for debugging purposes only.
1.1 Variable names
Variable names must be meaningful and represent the semantics of the variable.
Do not use a, b, c1, c2, ttt as
variable names.
Do use length, width, price and so on.
Exceptions. i,j,k,l are allowed as loop counter variables. x,y,z are allowed when representing
points in 2D or 3D space.
1.2 Abbreviations
In variable, type and function names use
consistent, meaningful abbreviations. E.g., if you choose to abbreviate
library
as
lib, do it throughout your program:
libCardNumber, libBookCollection, libVisited and so on.
1.3 Capitalization
Use the following rules for capitalizing identifiers:
- Variables
- always start with a lowercase letter; capitalize first letter of all other words in compound variable names.
Examples: x, startTime, myLastPaycheckAmount, isReached
- Function names
- same as variables.
Examples: search(), findMax(), isReached(), computePercentage()
- Data type names
- User-defined data type names start with a capital letter and capitalize the first letter of all words in compound type
names.
Examples: Buffer, StatTable,
- #defined constants
- Use ALLCAPS for #defined constants. If the name of a constant is compound, you are allowed
to use underscores
Examples BLUE, COLOR, BLOCK_SIZE, HIT_RATIO, MAX_WIDTH_OF_RECTANGLE
2. Constants
Your code shall not contain "magic numbers". Instead, #define all numeric constants you are planning
to you in your code and give them (see 1.1.) meaningful names.
The same should hold for non-numeric constants that you are planning to use for some specific purpose in the
code. E.g., if you need to use a literal 'a' in various char arithmetics ( inputChar - 'a' and similar
expressions), then #define it.
DO NOT #define numbers by giving them numeric names: #define SEVENTEEN 17 is just as bad as simply
using 17 in the code. Determine the meaning of 17 in your program and give it an appropriate name.
Sometimes you may need to #define the same number multiple times. E.g., if you need to use in your
program two constants: the number of years in school after kindergarden and the number of months in a year,
use these two declarations:
#define NUM_MONTHS 12
#define YEARS_OF_SCHOOL 12
and use each in the appropriate context.
Exceptions. Constants 0, 1, -1 and 2 can be used without being declared. In certain
contexts, 5, 10, 100 may be forgivable, and sometimes 255 (or 256) - check with me first.
Also, under most circumstances, no need to #define strings used in printf statements (unless you
are using the same string in multiple contexts, in which case #defines actually make sense).
3. Global Variables
You should never use global variables in your programs. If you think you should use global variables in
your program, see previous sentence. If you still think you should use them, talk to me.
4. Code Indentation
4.1. Indentation style
Use 3 space indentation in functions,
if,
switch statments and the loops. Use
spaces, NOT tabs to indent.
Your code should look like this:
int foo() {
declaration;
while (...) {
statement;
if (...) {
statement;
}
else {
statement;
}
}
}
4.2. Braces
Opening braces shall be placed on the same line as the function name,
if, switch, while, do, for keywords.
Closing braces must be on their own lines, flush with the first character of the line on which their opening brace
resides. See code fragement above.
4.3 "Orphans"
Always use curly braces for loop bodies and
if and
else bodies, even if the bodies themselves
contain just one statement (it is possible that at debug time you'll need to add more statements there, this make you ready for
this possibility).
Correct:
if (x == 1) {
x = x+1;
}
else {
x = x-1;
}
Incorrect
if (x==1) x=x+1
else x=x-1;
4.4. No Elseifs
C does not have
else ifs. The proper indentation is:
if (x) {
x++;
}
else {
if (y) {
...
}
else {
...
}
}
DO NOT USE THIS:
if (x) {
x++;
}
else if (y) {
...
}
else {
...
}
4.5. Line length
Line length cannot exceed 80 characters. Period. If your line is long, split it into multiple lines,
indent each subsequent line by 1 to 3 spaces:
x = arcTan(myFavoriteNumber + myLeastFavoriteNumber) + 27 -
sin(myFavoriteNumber / myLeastFavoriteNumber);
Alternatively, you can make the second line stick out on the right by 3-5 characters:
x = arcTan(myFavoriteNumber + myLeastFavoriteNumber) + 27 -
sin(myFavoriteNumber / myLeastFavoriteNumber);
4.6. Blank Lines
Insert blank lines in your code to break sequences of statements that are too long.
5. Program Organization
Unless explicitly allowed in your assignment, do not place code in .h files.
Use multiple .h and .c files, when is called for. Do not try to submit
entire program as a single .c file, unless specified in the assignment.
Put in .h files only declarations needed in multiple files.
5. Comments
5.1. Header Comments
Each
.c and
.h file you submit must contain a header comment at the top. The comment
shall contain, at the very least, the following information:
- Your name
- Date file was created (sometimes quarter/year is enough)
- Assignment this file relates to
- Brief explanation of the purpose of the file
If the file is part of a team submission, put team name and names of all students of the team on the header comment, regardless
of who actually created the file. You can use a separate comment to identify the specific author/authors.
5.2. Declaration Comments
Function declarations must come with short comments specifying the purpose of the function. The comment shall be placed above the
declaration. Describe the function interface (parameters, return).
Important
#defined constants must have a comment. Place the comment on the same line if possible, otherwise, place it above the
declaration.
Important local function variables need to have a comment. Don't declare a lot of different variables on the same line. Place
the comment on the same line as the declaration if possible, otherwise, place it above the declaration (if doing so, place
a blank line after the declaration).
5.3. Implementation Comments
Comments must be meaningful and explain what is going on. Do not leave trivial comments like
/* loop */ in front of a loop
when submitting. Some "housekeeping" comments are allowed - see below.
Keep your comments current and clear!
5.4. Housekeeping comments
The following "housekeeping" comments are permitted (I use them often to help me with reading the code).
- Indentation help. You can put comments of the form /* for loop */, /* if */, /* functionName() */ on
the line that contains the closing brace for the specific statement/function definition. If you have a heavily nested block of code, it
may help you identify what gets closed where.
- Program stage. In larger functions, you may place comments of the form /* ----- Stage 1: Getting the data ------ */
separated by blank lines on both sides in the body of your code. This allows for quick navigation to the appropriate block of code.
Don't do it, if blocks of code are less than 10-15 lines.
- Traceability information. When given detailed instructions in the form of numbered requirements for the behavior of a specific
function, you can trace your code to the numbered requirements, by placing traceability comments of the form
/* Requirement R1.1 */ at the beginning of the appropriate block of code. This not required of you, but sometimes may
be useful (esp. if the same block of code is worked on by multiple people).
September 22, 2013. dekhtyar@calpoly.edu