Hic Sunt Dracones

Comments are great

Posted on Friday, September 9, 2016
in Category Howto

When programming I write small programs all the time. Sometimes as a test bed when looking for a bug, sometimes to help understand a library, sometimes as a tool to do things for me. They are relatively small in general, a single file, few hundred lines of code max. And more often than not I keep them when done. As reference about how to use an API, because I think the tool is helpful or just because you never know if some spare bytes might be handy in the future. Quite often the command to compile the whole thing isn’t just a straight forward gcc as libraries need to be linked, C standards have to be specified, you name it. In the past I just had a comment in the top of all these files looking like this:

// gcc -Wall -g -o hello_world hello_world.c && ./hello_world

#include <stdio.h>

int main()
{
  int i; // <-- just to see some compiler output in the example
  printf("hello, world\n");
  return 0;
}

Whenever I came back to it I copy&pasted it to my shell and was happy. Now, given that I like to tinker I wanted to make that easier and quicker, so here is my new way of doing it:

#define SHELL_HELPER \
 gcc -Wall -g -o hello_world hello_world.c && ./hello_world; exit $?

#include <stdio.h>

int main()
{
  int i; // <-- just to see some compiler output in the example
  printf("hello, world\n");
  return 0;
}

With this I can now treat the C file as a shell script:

$ sh hello_world.c
hello_world.c: In function ‘main’:
hello_world.c:8:7: warning: unused variable ‘i’ [-Wunused-variable]
   int i; // <-- just to see some compiler output in the example
       ^
hello, world

The reason why that works is that the # is a comment in the shell, so it’s ignoring the first line. Then it executes the second which ends in a call to exit which terminates the script once the sources are compiled and the result run. The compiler on the other hand sees a #define in the first line, and as it ends in a backslash it also covers the second line. Thus it’s basically ignored.

Neat, isn’t it?

Addendum:

To make that shell snippet a little more versatile it can be replaced like this:

#define SHELL_HELPER \
 gcc -Wall -g -o "${0%.*}" "${0}" && "./${0%.*}"; exit $?

#include <stdio.h>

int main()
{
  int i; // <-- just to see some compiler output in the example
  printf("hello, world\n");
  return 0;
}