The Hows and Whys of Commenting C and C++ Code


By Alex Allain
Programs are meant to be beautiful. If someone tells you otherwise, you'd probably do best not to listen to the rest of his advice. A good program is beautiful in both its concept -- the algorithm used, the design, the flow of control -- but also in its readability. Good code is not replete with question mark colon operators and pointer arithmetic, or at least not when the code doesn't need to be optimized to save a few seconds every few months of operation. But readable code, while a nice ideal, often requires some help from the English (or from some other) language. Sometimes the algorithm is too complex to be understood rapidly or completely without some explanation, or the code requires some esoteric function call from the C library that has both a cryptic and a misleading name. And if you ever plan to code for a living, you will almost certainly have to go back several years later to modify the one section of code that you didn't feel like commenting -- or someone else will, and will curse your name. Finally, commenting code can also lead to a better understanding of the program and may help uncover bugs before testing. For both aesthetic and practical reasons, good commenting is an essential and often overlooked programming skill.



Before discussing how to comment, a few words of warning: it is possible to comment too much. Just as good writing is spare, so too is good coding. You do not want to include a comment telling the reader something obvious, or something that can be discerned from a single line of code. (You are probably not writing your code to teach someone how to program!) For instance, "int callCount = 0; //declares an integer variable," conveys no meaningful information. Comments should reveal the underlying structure of the code, not the surface details. A more meaningful comment would be "int callCount = 0; //holds number of calls to [function]."

Comments should not be overly long. Comments should not give details for the sake of details; only when a fact is necessary or interesting should it be brought to the attention of the program's reader. If you were reading someone else's program, you would not want to be forced to pick through paragraphs of text describing the intricacies of a for loop's operation only to realize that you could have discovered the same information simply by having read the for loop.

For the sake of future readers, you should generally include some header information at the top of your program. This information may include your name and contact information, the date the code was last modified, the purpose of the program, and if necessary, a brief exposition of the algorithm used or the design decisions made. You may also want to include a list of known bugs, inefficiencies, or suggestions for improvement. It is convenient to demarcate this section of the program file in a large comment block of the form
/********
*       *
*       *
********/
This form of comment is best done at the end of the program, except perhaps for an overview of the algorithm, which you may find helps to crystallize your thoughts when you are dealing with new, confusing, or complex concepts.

Second, whenever you create a new class or a new function definition, you should add a comment explaining what the class or function does. For a class, you should explain the purpose of the class, what publicly accessible functions and variables are available, any limitations of the class, and information that the programmer may need if he or she wanted to inherit from the class. When defining a function, you should describe what the function does and whether or not it has side effects such as changing global variables, interacting with the user, or so forth. It is also convenient to describe what sort of arguments the function takes and what, if any, value it returns: e.g., if you have a function findTime(int distance, int speed), you would want to tell the user that the distance is in rods, and the speed is in furlongs per fortnight, and that the function returns the time taken by the travel in epochs.

You could make the variable names more descriptive, but the increased descriptiveness is unnecessary inside the function because the relationship between distance and speed is the significant feature, not the relationship between distanceinrods and speedinfurlongsperfortnight. As you can see, long names are unnecessarily complex and can lead to hard-to-find typos. In general, variable names should be only descriptive enough to express the relationship between variables. Any implementation details should be handled by comments at points where the details may matter. For instance, in the above function, the function's caller must know the units, but those units do not matter inside the function (except when conversions are being made, but the programmer should make a note of this at the time of the conversion). In order to avoid confusion, you should eschew abbreviations; a word can be abbreviated many ways, and a single abbreviation can describe more than one word. Avoiding abbreviations avoids this problem.

Third, when adding comments directly to your code, be spare. The less you say, the better; if you force yourself to be precise, you will make the comments more helpful, and you will force yourself to synthesize the flow of your program rather than allow yourself to repeat what the code already tells the user. The code should fit seamlessly into the algorithm rather than wrap entirely around it and smother the logic embedded in the C++.

Fourth, good commenting can improve your programming. You can use them as an organizational device by including comments prior to filling in code -- for instance, when you have a long block of conditional statements, you may wish to comment what should happen when each conditional is executed before you flesh out the code. In doing so, you save yourself the burden of remembering the details of the entire program, allowing you to concentrate on the implementation of one aspect at a time. Additionally, when you force yourself to comment during the programming process, you cannot get away with writing code that "you hope will work" if you make yourself explain why it works. (Keep in mind that if the code is so complex that you don't know how it works, then you probably should be commenting it for the sake of both yourself and others.)

Finally, keep in mind that what seems obvious now may not seem obvious later. While you shouldn't excessively comment, do make sure to comment things that are nonstandard algorithms. You do not need to comment a programming idiom, but you do want to comment an algorithm you designed for the program, no matter how simple it may seem to you. No doubt it will seem foreign three weeks after you write the code, and if you plan (and even if you do not plan) to come back to the code, it will be immeasurably helpful.

Comments are for yourself and others. You may be forced to work with uncommented code, and it helps to comment the code as you work through what it does. This can be as simple as renaming the variable names from, say, r, x, and y to currentNumber, largestPrime, and currentDivisor. With any luck, after one or two of these experiences you will recognize the wisdom of commenting your code. Moreover, you will see the greater elegance of a well-commented, carefully written piece of code in comparison to a hack thrown together only to "work." Related Articles

Programming Style: Why Whitespace Matters, and how to use (and avoid misusing) it

How you can write readable code, and why you should

Naming Conventions, and Names you Should Avoid