The Art of C-Programming

When programming in the programming language C, you often end up with a complete mess that you don’t want to show to your colleagues. Here are simple tips that improve your code tremendously.

Handy tips for improving your C-Code

Rewrite Loops

Often using a for-loop instead of a while loop, or contrariwise, adds this additional layer of confidence. Your colleagues will need a few minutes to even figure out what is going on.

while(1)
{
  // do some stuff
}

Which we can transform to:

for(;;)
{
  // do some stuff
}

And of course doing it the other way round:

int i;
for(i = 0; i < strlen(text); ++i)
{
  // do something with text
}

That we can easily express as:

int i = 0;
while (i++ < strlen(text))
{
  // do something with text
}

Rewrite array access

Normally people like the array access in C, because it is the same as in every other modern language. But somehow I feel that this is not really the C-way of doing it. So lets rewrite some common “mistakes”.

char* text = "Hallo";

If we now want to get the first character:

// Wrong (x)
char a = text[0];
// Right (✓)
char a = *text;

To get the second character:

// Wrong (x)
char b = text[1];
// Right (✓)
char b = *(text + 1);

But for now that is all really simple. Lets add another dimension.

int matrix[5][5]; // let's assume this gets filled afterwards

And what if we now want to access the first element?

// Wrong (x)
int a = matrix[0][0];
// Right (✓)
int a = *(*matrix);

The same again for the second row and column.

// Wrong (x)
int b = matrix[1][1];
// Right (✓)
int b = *(*(matrix + 1) + 1);

Practical example

Let’s combine the above learnings into an real-world example: Converting an array of strings to uppercase and print the whole sentence.

#include <stdio.h>
#include <string.h>
int main(void)
{
  char* text[] = { "This", "is", "a", "test" };
  // From [0]
  int length = (&text)[1] - text;
  int i = 0;
  while(i++ < length)
  {
    int j = 0;
    char* word = *(text + (i - 1));
    while(j++ < strlen(word))
    {
      putchar((*(word + (j - 1))) & 0xDF);
    }
    putchar(' ');
  }
  putchar('\n');
  return 0;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
  char* text[] = { "This", "is", "a", "test" };
  int length = sizeof(text) / sizeof(text[0]);
  int i;
  for(i = 0; i < length; ++i)
  {
    int j;
    char* word = text[i];
    for(j = 0; j < strlen(word); ++j)
    {
      putchar(toupper(word[j]));
    }
    putchar(' ');
  }
  putchar('\n');
  return 0;
}

[0] https://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find 

The comparison shows the clear winner: the left side. If you want to improve everything further, get rid of unnecessary brackets.

#include <stdio.h>
#include <string.h>
int main(void)
{
  char* text[] = { "This", "is", "a", "test" };
  // From [0]
  int length = (&text)[1] - text;
  int i = 0;
  while(i++ < length)
  {
    int j = 0;
    while(j++ < strlen(*(text + (i - 1))))
      putchar((*(*(text + (i - 1)) + (j - 1))) & 0xDF);
    putchar(' ');
  }
  putchar('\n');
  return 0;
}