
\documentclass[12pt]{article}
\usepackage[T2A,OT1]{fontenc}
\usepackage[default]{cantarell}
\usepackage[a4paper, top=20mm, bottom=20mm, left=20mm, right=20mm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[russian, english]{babel}
\usepackage{tabu}
\usepackage{hyperref}
\usepackage{parskip}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage[normalem]{ulem}
\usepackage{float}
\floatstyle{boxed}
\restylefloat{figure}
\usepackage{setspace}
\onehalfspacing
\author{Artyom Bologov \href{mailto:making-c-uglier@aartaka.me}{(email)}}
\date{\today}
\title{Making C Code Uglier}
\makeatletter
\def\endenv{\expandafter\end\expandafter{\@currenvir}}
\makeatother
\begin{document}
\maketitle

C++ is practical, yet sometimes scary.
C is outright frightening. If someone writes code in C++, they must be smart.
If someone writes code in C, they must be crazy (well, at least I am.)

But still, C—with its guts full of eldritch horrors—is
the lingua franca of programming and the most portable assembly language.

C is readable enough to most programmers, because most mainstream languages
are
\href{https://wikipedia.org/wiki/List_of_C-family_programming_languages}{C progenies}.
Pointers and macros are loathsome, but they are rare enough (are they?) to ignore.

So how scary can C code get?
Not as a production use, but rather as an exercise in aesthetics.
This post goes through a set of things that can convolute/obfuscate C code,
from the minute details to critical readability losses.

Note that some obvious things like

\begin{itemize}\item Inconsistency.
\item Typos.
\item Bad naming.
\item \href{https://wiki.c2.com/?ThreeStarProgrammer}{Pointer abuse}.
\end{itemize}

are not mentioned to leave space for the scarier ones.

\section*{Test Program} \label{test-program}

I'm going to use a slightly modified
\href{"https://wikipedia.org/wiki/TPK_algorithm#C_implementation"}{C version of Trabb Pardo Knuth algorithm}
from Wikipedia because it's small enough
while still showcasing most of C constructs/features:

\begin{figure}[h!]\begin{verbatim}
#include <math.h>;
#include <stdio.h>;

double f (double t)
{
    return sqrt(fabs(t)) + 5 * pow(t, 3);
}

void tpk (void)
{
    double y, a[11] = {0};
    for (int i = 0; i < 11; i++)
         scanf("%lf", \&la[i]);

    for (int i = 10; i >= 0; i--)
        if ((y = f(a[i])) > 400)
            printf("%d TOO LARGE\n", i);
        else
            printf("%d %.16g\n", i, y);
}

int main (void)
{
    tpk();
    return 0;
}
\end{verbatim}\caption{Trabb Pardo Knuth algorithm implementation in C}\end{figure}

\section*{Benign: Indentation and Bracket Placement Style} \label{style}

Two of four spaces? Eight? Or three, maybe?
Or—God almighty—tabs?
\href{https://wikipedia.org/wiki/Indentation_style}{C code styles are numerous}
and these styles have only one thing in common:
all the styles are mutually incompatible and un-aesthetic.
No matter which style one prefers—they're delusional and wrong,
at least to the ones exhorting another style.

I use Linux kernel style, which might make you scream from the 8 spaces-wide tabs. But I'm not surrendering it.

As a matter of example, I'll use the Pico indentation style (four/five spaces)
and bracket placement (before the first expression and after the last one.)
Plus added spaces mimicking the Glib style:

\begin{figure}[h!]\begin{verbatim}
double
f (double t)
{   return
    sqrt (fabs (t)) + 5 * pow (t, 3); }
\end{verbatim}\caption{Sub-function of TPK algorithm re-indented in Pico style}\end{figure}

Ugh, block scope and control flow are illegible now.

\section*{Confusing: Subscripts} \label{subscripts}

A queer behavior of the standard array subscripts:
the index and array parts can be swapped:

\begin{figure}[h!]\begin{verbatim}
double a[11] = {0}, y;
for (int i = 0; i < 11; i++)
        scanf ("%lf", \&i[a]);
\end{verbatim}\caption{Inner loop code with confusingly reversed array subscripts}\end{figure}

This reversal is modest, but nonetheless galling.

An exercise to the reader: can you find the exact spot where the subscript is reversed?

\section*{Antiquated: K \& R style} \label{k-n-r-style}

That's where the post gets shuddery.
K \& R style, or, as they call it, "I don't understand old C code".

\begin{figure}[h!]\begin{verbatim}
double
f(t)
double t;
{   return
    sqrt (fabs (t)) + 5 * pow (t, 3); }
\end{verbatim}\caption{A function rewritten with types after the parameter list}\end{figure}

This style

\begin{itemize}\item duplicates parameter names,
\item moves the type information further away from the parameter list,
\item removes the typing information from the function.
\end{itemize}

Luckily, C23 finally removes it,
after more than thirty years of yielding to the horror
and maintaining it in deprecated status.

\section*{Smart: Recursion} \label{recursion}

Reordering and refactoring functions is always fun.
So how about turning all the for-loops into recursion?
Recursion is cool, I've heard.
So here's a recursive rendering of the number printing loop:

\begin{figure}[h!]\begin{verbatim}
void
print_nums(a, i)
double *a;
int i;
{    if (i < 0)
         return;
     double y = f (i[a]);
     if (y > 400)
         printf ("%d TOO LARGE\n", i);
     else
         printf ("%d %.16g\n", i, y);
     print_nums (a, --i); }
\end{verbatim}\caption{Number printing loop refactored as a recursive function folded over an array}\end{figure}

Five more code lines, lots of stack frames (unless you have tail call elimination),
and overall less comprehensible control flow. Yay!

\paragraph{Recursion is good, actually} \begin{quote}
Like some un-aesthetic and alienating changes this page lists, recursion might be useful. It can make your algorithms simple and powerful when done right. I often use recursion when writing Lisp. But I can relate to people seeing it as vile and perplexing.
\end{quote}

\section*{Terse: Ternaries} \label{ternaries}

This is my favorite: switching from if-else to ternaries.
It's shorter, expression-only, and it makes code look more daunting.
And there's a rumor that compilers increase the optimization level
when they see ternaries.
Likely, out of regard for programmer's bravery.

\begin{figure}[h!]\begin{verbatim}
void
print_nums (a, i)
double *a;
int i;
{    double y;
     (i < 0) ? 0 :
               (y = f (i[a]),
                (y > 400 ? printf ("%d TOO LARGE\n", i) :
                           printf ("%d %.16g\n", i, y)))
               print_nums (a, --i); }
\end{verbatim}\caption{Code with if statements replaced with ternaries}\end{figure}

If only comma operator allowed for variable declaration
(wink wink C standard committee),
this function might've had no \verb|double y| in it either.
But, for now, let this stateful statement stay there.

\paragraph{Ternaries are good, actually} \begin{quote}
I like the ternary-formatted code because it forces a side effect-less algos where I want it to. It's even more useful in other C-like languages because they have less restrictive blocks and more abstractions compatible with functional style.
\end{quote}

\section*{Unconventional: Delimiter-First Code} \label{delimiter-first}

There are reasons one can use
\href{https://arogozhnikov.github.io/2022/11/29/delimiter-comes-first.html}{leading-delimiter style in SQL and Haskell}.
But in other languages...

\begin{figure}[h!]\begin{verbatim}
void
print_nums (a, i)
double *a;
int i;
{    double y;
     (i < 0)
     ? 0
     : (y = f (i[a])
        , (y > 400
           ? printf ("%d TOO LARGE\n"
                     , i)
           : printf ("%d %.16g\n"
                     , i, y))
        , print_nums (a, --i)); }
\end{verbatim}\caption{Using leading commas and ternaries in function calls}\end{figure}

I like how the ternaries become more pronounced
and how it promotes a functional-ish style.
But I bet, your eyes are already hemorrhaging,
so feel free to ignore my aesthetic preferences.

\section*{Awful: Alternative representations} \label{alt-representations}

That's the most horrifying one:
C has alternatives to some characters
that weren't there at the time of the first standard.
There are two-(digraphs)
and three-character (trigraphs, deprecated in C23) encodings
for \verb|[|, \verb|^|, \verb|{| etc.
Here's a table of transformations:

Table omitted due to complexity, check the HTML version instead.


And here's the code with encoded parts:

\begin{figure}[h!]\begin{verbatim}
void
read_nums (a, i)
double *a;
int i;
<%  if (i == 11)
    <%  return; %>
    else
        <%  scanf ("%lf", \&i <:a:>);
        read_nums (a, ++i);%> %>
\end{verbatim}\caption{C code using digraphs}\end{figure}

And that's just digraphs, trigraphs are even worse!

\paragraph{Alternative representations are good, actually} \begin{quote}
There is a more useful side to alternative encodings.
\verb|<iso646.h>| provides the spelled-out logical operators
far more readable than single-character operators:

\begin{table} \begin{tabularx}{0.8\textwidth}
\hline C operator & iso646.h spelled-out macro \\ \hline
\&\& & and \\
\&= & and_eq \\
\& & bitand \\
| & bitor \\
~ & compl \\
! & not \\
!= & not_eq \\
|| & or \\
|= & or_eq \\
^ & xor \\
^= & xor_eq \\
\end{tabularx} \caption{Relatively unreadable C operators vs. respective iso646.h macros} \end{table}

Even though it's atypical, I'm tempted to use these in my projects.
\end{quote}

\section*{Wrapping Up} \label{wrapping-up}

Here's the final code for TPK algorithm.
It compiles under Clang 13.0.1 on my \verb|x86_64-unknown-linux-gnu| 😵
(the exact command is \verb|clang tpk.c -trigraphs -lm|.)

\begin{figure}[h!]\begin{verbatim}
%:include <math.h>;
??=include <stdio.h>;

double
f(t)
double t;
??< return
    sqrt (fabs (t))
    + 5
    * pow (t
           , 3); %>

void
read_nums(a, i)
double *a;
int i;
<%  if (i == 11)
    &lt%  return; %>
    else
    ??&lt scanf ("%lf"
                 , &ampi<:a??));
        read_nums (a
                   , ++i);%> %>


void
print_nums(a, i)
double *a;
int i;
<%   double y;
     (i < 0)
     ? 0
     : (y = f (i??(a:>)
        , (y > 400
           ? printf ("%d TOO LARGE\n"
                     , i)
           : printf ("%d %.16g\n"
                     , i, y))
        , print_nums (a
                      , --i)); ??>

void tpk ()
 ??< double a <:11:> = ??<0??>
           , y;
    read_nums (a
               , 0);
    print_nums (a
                , 10);
    /* Absolutely unnecessary, but irritating. */
    return; %>

int main ()
&lt%  tpk();
    return 0; ??>
\end{verbatim}\caption{Final code with all the ugly gotchas above applied}\end{figure}

If you want some job security as a C or C++ programmer,
you might use some of the things discussed above.
But in any other scenario: you don't want to write code this way!
Be kind to each other, even when y'all write chthonic C code.

Update: some commenters on Reddit mentioned
\href{https://ioccc.org}{IOCCC}
as an additional inspiration and further research direction.
This post is by no means exhaustive,
and you will likely find much more gory details if you explore IOCCC.

Another update:
\href{https://reddit.com/user/insanelygreat}{u/insanelygreat}
shared an absolutely horrendous piece of code
and set of macros that turn C into something BASIC.
Here's a small piece of code from their
\href{https://www.reddit.com/r/C_Programming/comments/17sfc4a/comment/k8q39ij}{comment you should read in full}:

\begin{figure}[h!]\begin{verbatim}
/* check for meta chars */
BEGIN
   REG BOOL slash; slash=0;
   WHILE !fngchar(*cs)
   DO   IF *cs++==0
        THEN    IF rflg ANDF slash THEN break; ELSE return(0) FI
        ELIF *cs=='/'
        THEN    slash++;
        FI
   OD
END
\end{verbatim}\caption{Heavily macro-infused piece of C code that looks like shouting in Ada (citing u/insanelygreat)}\end{figure}


\par\noindent\rule{\textwidth}{0.4pt}
\href{https://creativecommons.org/licenses/by/4.0}{CC-BY 4.0} 2022-2026 by Artyom Bologov (aartaka,)
\href{https://codeberg.org/aartaka/pages/commit/a91befa}{with one commit remixing Claude-generated code}.
Any and all opinions listed here are my own and not representative of my employers; future, past and present.
\end{document}
