When printing out multiple lines of text in C, it is common to see code like this:
printf ("+--------------------+\n");
printf ("| Welcome to my BBS! |\n");
printf ("+--------------------+\n");
printf ("| C)hat G)oodbye |\n");
printf ("| E)mail H)elp |\n");
printf ("+--------------------+\n");
That looks okay, but is calling a function for each line. You could just as easily combine multiple lines and embed the “\n” new line escape code in one long string.
printf ("+--------------------+\n| Welcome to my BBS! |\n+--------------------+\n| C)hat G)oodbye |\n| E)mail H)elp |\n+--------------------+\n");
Not only does it make the code a bit smaller (no overhead of making the printf call multiple times), it should be a bit faster since it removes the overhead of going in and out of a function.
But man is that ugly.
At some point, I learned about the automatic string concatenation that the C preprocessor (?) does. That allows you to break up quoted lines like this:
const char *message = "This is a very long message that is too wide for "
"my source code editor so I split it up into separate lines.\n";
“Back in the day” if you had C code that went to the next line, you were supposed to put a \ at the end of the line.
if ((something == true) && \
(somethingElse == false) && \
(somethingCompletelyDifferent == banana))
{
…but modern compilers do not seem to care about source code line length, so you can usually do this:
printf ("+--------------------+\n"
"| Welcome to my BBS! |\n"
"+--------------------+\n"
"| C)hat G)oodbye |\n"
"| E)mail H)elp |\n"
"+--------------------+\n");
That looks odd if you aren’t aware of it, but makes for efficient code that is easy to read.
However, not all compilers are created equally. A previous job used a compiler that did not allow constant strings any longer than 80 characters! If you did something like this, it would not compile:
printf ("12345678901234567890123456789012345678901234567890123456789012345678901234567890x");
I had to contact their support to have them explain the weird error it gave me. On that compiler, trying to do this would also fail:
printf ("1234567890"
"1234567890"
"1234567890"
"1234567890"
"1234567890"
"1234567890"
"1234567890"
"1234567890x");
But that is not important to the story. I just mention it to explain that my background as an embedded C programmer has me limited, often, by sub-standard C compilers that do not support all the greatness you might get on a PC/Mac compiler.
These days, I tend to break all my multi-line prints up like that, so the source code resembles the output:
printf ("This is the first line.\n"
"\n"
"And we skipped a line above and below.\n"
"\n"
"The end.\n");
I know that may look odd, but it visually indicates that there will be a skipped line between those lines of text, where this does not:
printf ("This is the first line.\n\n"
"And we skipped a line above and below.\n\n"
"The end.\n");
Do any of you do this?
And, while today any monitor will display more than 80 columns, printers still default to this 80 column text. Sure, you can downsize the font (but the older I get, the less I want to read small print). Some coding standards I have worked under want source code lines to be under 80 characters, which does make doing a printout code review much easier.
And this led me to breaking up long lines like this…
printf ("This is a very long line that is too long for our"
"80 character printout\n");
That code would print one line of text, but the source is short enough to fit within the 80 column width preferred by that coding standard.
And here is why I hate it…
I have split lines up like this in the past, and created issues when I later tried to find where in the code some message was generated. For example, if I wanted to find “This is a very long line that is too long for our 80 character printout” and searched for that full string, it would not show up. It does not exist in the source code. It has a break in between.
Even searching for “our 80 character” would not be found due to this.
And that’s the downside of what I just presented, and why you may not want to do it that way.
Thank you for coming to my presentation.
In C, it’s #define that is defined on one line, so the backslash is needed if you write a macro across lines. C itself is happy treating newlines as whitespace. Also, if a C compiler says it conforms to C89 (for the language; it doesn’t need to come with the standard C library), then it has to support string literals as long as 512 bytes (minimum, a C compiler can support more).
As such, can’t you bitch at the C vendor? Threaten to switch away? Or are all embedded-C compilers such trash fires?
Most are “C like”. When building for a system with 32K flash and 8K RAM, one can’t even fit a full implementation of printf ;)
Side track: With how bloated modern editors are (looking at you, VScode), I think it’s reasonable for the find function to find strings even if they are separated like in your example where a regular editor can’t find the string.
Like how can a modern editor otherwise justify requiring a processor speed in the GHz range, when you could do most of the other things with the editors we had 30 years ago?
Interesting. A C-pre processor aware search mode!
Actually, it would be cool if an editor could scan the project files and have a toggle to show you all the defines and macros and such substituted already in the code.
f = BIT(7);
But it shows…
f = 128;
Does anything do that???