Many Algol-derived languages have a puzzling "feature" called null statements. When they creep into a program, they go largely unnoticed like a bit of defunct DNA in a cell; if we notice one or it causes an error, we wonder why the compiler didn't detect and report it as a syntax error. Rarely, when used appropriately, a null statement can create compact and efficient code. When used inadvertently, the result ranges from a benign, extraneous semicolon to a hard-to-find logical error. Whether a null statement is benign (2) or malignant (2) is a product of where it appears in a program.
Although they are often confusing and their utility is questionable, they are nevertheless a valid part of many languages that we must necessarily understand. It's crucial to begin training yourself to spot null statements and to distinguish when they are helpful, benign, or malignant.
A C++ program consists of a sequence of statements. Each statement is a computer instruction terminated with a semicolon. A null statement is an empty statement marked by an unneeded semicolon. They are legal, if unnecessary, anywhere in a program where a statement is valid. That is, stray semicolons create null statements, which can happen anywhere. Sometimes, null statements are benign and just look "out of place" without causing any problems.
...;
;
...; |
count = index + length;; for (int i = 0; i < 10; i++) cout << i << endl;; |
(a) | (b) |
It only takes a small movement to make a benign null statement malignant, introducing a difficult-to-locate logical error into a program. Sometimes, a misplaced semicolon does cause a syntax error. The compiler component typically detects and reports syntax errors, including misplaced semicolons. Although not always accurate, the report includes the syntax error's location, serving as a starting point for localizing the error. Alternatively, The compiler system cannot detect logical errors, leaving their detection, identification, and correction to programmers.
for (int i = 0; i < 10; i++);
cout << i << endl;
|
int i;
for (i = 0; i < 10; i++);
cout << i << endl; |
for (i = 0; i < 10; i++);
cout << "Hello World" << endl;
|
(a) | (b) | (c) |
If the null statements illustrated in these examples represent program errors, why doesn't the compiler detect and report the null statements? Part of the answer is that null statements are sometimes, albeit rarely, useful.
Developing an authentic example of a helpful null statement is challenging; developing one that doesn't use features the text introduces later is more difficult. Nevertheless, the following example is from a program I wrote while working as a software engineer. My responsibilities included conducting the annual FORTRAN compiler ANSI-compliance validation required by the Federal Government. The validator arrived on site with a 9-track magnetic tape containing the validation programs formatted as a sequence of 80-column punch cards. My extraction program read the tape and formatted the validation programs for our operating system.
Although null statements can appear at any location in a program where a "regular" statement is legal, they are rarely useful outside of for and while loops. In contrast, they often introduce subtle bugs.
if (counter < 10);
|
for (int i = 0; i < 10; i++);
|
for (int = 0; i > 10; i++);
cout << i * i << endl; |