Hi list!
Having this code:
do {
if (flag_prg)
printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER);
^
Typo? Strange to have a lower case letter on the end of an all-caps
macro. I take it this is a plural, implying that expands into a
string literal containing two numbers separated by a period,
specifying the width an pecision for %s?
} while (0)
why the use of while?
That allows the whole thing to be a syntactically encapsulated statement
which requires a terminating semicolon, which is useful if it is
the expansion of a macro.
Suppose that you drop the do/while(0) and your macro just
expands this (note dropped semicolon).
if (flag_prg)
printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER)
Unlike do/while(0) this has problems. For instance, you can now
do something like this:
MACRO() + 3;
The + 3 happily goes onto the printf, so that it's obvious that MACRO()
is not a proper statement. But is it an expression? If so, this
should work:
var = MACRO();
but, nope, that breaks! You're assigning the value of an if statement,
oops!
Moreover, here is the kicker:
MACRO()
else { ... }
Look ma, you can continue the if statement that is started within the
macro expansion, by adding an else, and there is no compiler diagostic.
So you see this do/while(0) wrapping protects against crap like this.
Another good question is, why the cryptic compile-time string literal
manipulation instead of something straightforward, like:
prinf("%-*.*s", PROGNAME_WIDTH, PROGNAME_LIMIT, PROGNAME_BANNER);
A conversion like
"%-42.40s", string
isn't necessarily faster than
"%*.*s", width, prec, string
the reason is that if the format string is being interpreted, then the
42 and 40 have to be scanned and turned into values. Whereas the *
character allows printf to simply retrieve a ready-made integer value
from the arguments; no text-to-int conversion necessary.
You might have a performance win here if your your implementation has a
printf compiler which turns format strings into code.
Also, what is the purpose of this juxtaposition:
" " PROGNAME_BANNER
The extra space can easily be added under the control of the printf
format string. It's silly to be adding padding to the data.
Rather than "%s", " " MY_STRING you can just " %s", MY_STRING.