Question

How sykes2.c Works: Explaining an Obfuscated C Program That Prints __TIME__

cobfuscationdeobfuscation

Question

How does this C program work?

main(_) {
    _ ^ 448 && main(-~_);
    putchar(
        --_ % 64
            ? 32 | -~7[__TIME__ - _ / 8 % 8][">'txiZ^(~z?" - 48]
                  >> ";;;====~$::199"[_ * 2 & 8 | _ / 64]
                  / (_ & 2 ? 1 : 8) % 8 & 1
            : 10
    );
}

It compiles as written and prints the compilation time as large block-style digits based on the __TIME__ macro. For example, it can produce output like this:

!!  !!!!!!              !!  !!!!!!              !!  !!!!!!
!!  !!  !!              !!      !!              !!  !!  !!
!!  !!  !!              !!      !!              !!  !!  !!
!!  !!!!!!    !!        !!      !!    !!        !!  !!!!!!
!!      !!              !!      !!              !!  !!  !!
!!      !!              !!      !!              !!  !!  !!
!!  !!!!!!              !!      !!              !!  !!!!!!!

The main goal is to understand the ideas behind this code: recursion, implicit int, unusual array indexing, use of __TIME__, bit manipulation, and how the expression inside putchar() decides whether to print a space, !, or a newline.

Short Answer

By the end of this page, you will understand how an obfuscated C program can generate output from a compile-time string using recursion and bit operations. You will see how sykes2.c uses __TIME__, strange-but-valid indexing like 7[array], character arithmetic, and a compact bitmap technique to draw large digits one character at a time.

Concept

What concept is this code teaching?

This program is mainly about decoding dense C expressions. It combines several core C ideas:

  • Recursion to simulate a loop
  • The __TIME__ predefined macro to get the compile time as a string like "12:34:56"
  • Array indexing equivalence: a[b] is the same as *(a + b), so 7[s] is valid C
  • Bit manipulation to store and read pixel patterns for digits
  • ASCII character arithmetic to turn bit results into printable characters
  • Short-circuit logic and the conditional operator ?:

Why this matters

Obfuscated code is intentionally hard to read, but learning to unpack it helps you build real skills:

  • reading unfamiliar legacy code
  • tracing expressions carefully
  • understanding operator precedence
  • recognizing when code is using compact data encodings
  • separating what a program does from how strangely it is written

What the program is really doing

At a high level, the program:

  1. Counts through positions in a 7-row text grid
  2. Decides whether the current position should be a newline or a visible character
  3. Maps each text cell to one of the 8 characters in __TIME__
  4. Looks up the correct segment/pixel for that character
  5. Prints either a space or !

The result is a large digital-style rendering of the compile time.

Important older-C details used here

This program relies on old C behavior that modern code should avoid:

  • main(_) means main has an implicit return type of int
  • _ has no declared type, so it also defaults to int
  • putchar is used without including <stdio.h>

Modern C would write these explicitly and include headers. The code works mainly because older rules and permissive compiler behavior allow it.

Mental Model

Think of this program as a tiny printer head moving across a rectangular banner.

  • The banner has 7 rows.
  • Each row contains spaces and ! characters.
  • The program moves through the banner one cell at a time.
  • For each cell, it asks:
    • Is this the end of the line? Print \n.
    • Otherwise, which character of __TIME__ am I drawing here?
    • Which row of that digit am I in?
    • Does that pixel need to be on or off?

If the pixel is on, it prints !. If the pixel is off, it prints a space.

A good analogy is a dot-matrix sign:

  • the compile time string is the text to display
  • the encoded strings are the font data
  • the bit shifts and masks are how the program checks whether one dot should light up
Take Quiz

Syntax and Examples

Core syntax pieces used in this program

1. Recursive countdown or count-up trick

void f(int n) {
    if (n < 5) {
        f(n + 1);
    }
    printf("%d\n", n);
}

This calls itself before printing. The obfuscated program uses the same idea, but much more compactly:

_ ^ 448 && main(-~_);

Explanation:

  • -~_ means _ + 1
  • _ ^ 448 is zero only when _ == 448
  • A && B evaluates B only if A is nonzero

So this means roughly:

if (_ != 448) {
    main(_ + 1);
}

2. a[b] is the same as b[a]

char s[] = "hello";
printf("%c\n", s[1]);   // e
printf("%c\n", 1[s]);   // e

Why? Because:

s[1] == *(s + 1)
1[s] == *(1 + s)

So this strange expression is legal:

7[__TIME__ - _ / 8 % 8]

It means:

(__TIME__ - _ / 8 % 8)[7]

which is the same as:

__TIME__[7 - (_ / 8 % 8)]

3. Using __TIME__

printf("%s\n", __TIME__);

This expands at compile time to a string like:

"14:53:07"

Indexes:

IndexCharacter
0hour tens
1hour ones
2:
3minute tens
4minute ones
5:
6second tens
7second ones

4. Turning a bit into a printable character

A common bit test looks like this:

int bit = (value >> shift) & 1;

If bit is 0 or 1, you can map it to visible output:

putchar(bit ? '!' : ' ');

The obfuscated code instead uses:

32 | bit

Since:

  • 32 | 0 is ASCII 32, which is ' '
  • 32 | 1 is ASCII 33, which is '!'

That is a compact trick for choosing between space and exclamation mark.

Beginner-friendly simplified version

Here is a readable sketch of the main printing idea:

#include <stdio.h>

int main(void) {
    const char *t = __TIME__;

    for (int row = 0; row < 7; row++) {
        for (int col = 0; col < 64; col++) {
            int ch_index = col / 8;   // which character in time string
            int local_col = col % 8;  // column inside that character cell

            char c = t[ch_index];

            /* In the real obfuscated code, font data is packed into strings
               and extracted with shifts and masks. */
            int pixel_on = 0; /* placeholder */

            putchar(pixel_on ? '!' : ' ');
        }
        putchar('\n');
    }

    return 0;
}

This is not the same implementation, but it matches the structure: rows, columns, character lookup, pixel lookup, print.

Step by Step Execution

A smaller traceable fragment

The hardest part of sykes2.c is that everything happens in one expression. So first, isolate the control flow:

main(_) {
    _ ^ 448 && main(-~_);
    putchar(--_ % 64 ? 'X' : '\n');
}

This is not the original output logic, but it shows the order clearly.

What main(-~_) means

-~_

Bitwise NOT flips bits, so:

  • ~x is bitwise NOT
  • -~x is a well-known trick for x + 1

Example:

  • if _ = 5
  • ~5 = -6
  • -(-6) = 6

So main(-~_) means main(_ + 1).

What _ ^ 448 && main(-~_) does

The XOR expression _ ^ 448 is zero only when _ == 448.

So:

_ ^ 448 && main(-~_);

behaves like:

if (_ != 448) {
    main(_ + 1);
}

Why the output appears in forward order

Because the recursive call happens before putchar, output happens while the recursion unwinds.

That means the deepest call prints first.

Grid size

The code uses 448 because:

  • 64 columns per row
  • 7 rows
  • 64 * 7 = 448

So it prints exactly 448 characters, arranged as 7 lines of 64 positions, with a newline at the end of each row.

Newline logic

This part chooses newline vs regular character:

--_ % 64 ? ... : 10

Explanation:

  • --_ decrements _ before using it
  • if --_ % 64 is nonzero, print a normal cell
  • if it is zero, print 10, which is \n

So every 64th position becomes a newline.

Character selection

Inside a row, each time character occupies 8 columns.

This piece selects which character from __TIME__ is being drawn:

7[__TIME__ - _ / 8 % 8]

Rewrite it step by step:

(__TIME__ - (_ / 8 % 8))[7]

which becomes:

__TIME__[7 - (_ / 8 % 8)]

So the current column block picks one of the 8 characters of the time string.

Row selection

This piece selects the current output row:

_*2 & 8

This produces one of a small set of values used as part of indexing into the packed font data. It is a compact way to distinguish between groups of rows.

This part:

_/64

identifies which of the 7 text rows is currently being printed.

Together they help choose the correct encoded font row.

Font lookup

The code stores drawing information in string constants such as:

">'txiZ^(~z?"
";;;====~$::199"

These are not meant to be read as text. They are compact numeric storage:

  • each character has an ASCII value
  • that value is treated like packed bits
  • the code shifts and masks those bits to test whether a pixel is on

Final pixel decision

The important tail of the expression is effectively:

(... >> shift) / divisor % 8 & 1

This reduces to either 0 or 1.

Then:

32 | bit

turns that into:

  • 32 -> ' '
  • 33 -> '!'

So each cell prints either a space or an exclamation mark.

Big picture of one cell

For each printable position, the code does this:

  1. Determine current row and column
  2. Map the column to one of the 8 characters in __TIME__
  3. Read the actual time character, such as '4' or ':'
  4. Convert that character into an index into encoded font data
  5. Extract one bit for the current pixel
  6. Print '!' if the bit is 1, otherwise print a space

Real World Use Cases

Why learn from code like this?

You would not write production code in this style, but the underlying techniques are useful.

1. Reading compact encodings

Real programs often store data in compressed or packed form:

  • bitmap fonts
  • image masks
  • protocol flags
  • hardware register values
  • feature bitsets

This program is effectively reading a tiny packed font.

2. Understanding generated output

Many tools create text output from data:

  • CLI dashboards
  • ASCII charts
  • terminal clocks
  • log formatting tools
  • status displays in scripts

The program turns a string into a formatted text banner.

3. Working with compile-time macros

Predefined macros like __TIME__, __DATE__, and __FILE__ are often used for:

  • build information
  • debug output
  • version banners
  • generated metadata

Example:

printf("Built at %s on %s\n", __TIME__, __DATE__);

4. Operator precedence awareness

Even if you never write code like this, you must be able to read expressions involving:

  • &&
  • ?:
  • bitwise operators
  • shifts
  • arithmetic
  • array indexing

That matters in systems code, embedded code, and performance-sensitive C.

Take Quiz

Real Codebase Usage

How developers use these ideas in real C projects

Guard clauses and readable control flow

Instead of this obfuscated recursion:

_ ^ 448 && main(-~_);

real code would use a loop or a clear base case:

for (int i = 0; i < 448; i++) {
    /* print one cell */
}

or

if (i == limit) return;

Validation and explicit declarations

Production code should include headers and types explicitly:

#include <stdio.h>

int main(void) {
    puts(__TIME__);
    return 0;
}

Packed data tables

Developers do use packed tables, especially for:

  • embedded fonts
  • lookup tables
  • state machines
  • parsers
  • codecs

But they are usually written with names and comments:

static const unsigned char digit_font[10][7] = {
    /* ... */
};

Early returns and readable branching

Instead of embedding everything inside one putchar(...), real code separates steps:

int pixel = get_pixel(character, row, col);
putchar(pixel ? '!' : ' ');

This makes debugging easier.

Configuration by constants

This obfuscated code hides constants like:

  • total cells: 448
  • columns per row: 64
  • rows: 7
  • character width: 8

In a real project, these would be named:

#define ROWS 7
#define COLS 64
#define CHAR_WIDTH 8

Common Mistakes

1. Thinking 7[s] is invalid C

Broken assumption:

char *s = "abc";
/* many beginners think this is illegal */
printf("%c\n", 1[s]);

It is valid because a[b] means *(a + b).

2. Forgetting that old C allows implicit int

This program uses:

main(_)

In modern C, you should write:

int main(void)

or with parameters:

int main(int argc, char **argv)

Relying on implicit int is outdated and nonportable.

3. Misreading -~x

Broken interpretation:

int y = -~x; /* some think this means negative something strange */

In practice, this is just x + 1.

Prefer the readable version:

int y = x + 1;

4. Ignoring operator precedence

Expressions like this are easy to misread:

32 | value >> 2 & 1

A safer form is:

32 | ((value >> 2) & 1)

When learning, always add parentheses.

5. Assuming strings are always used as text

In this code, strings such as:

">'txiZ^(~z?"

are really compact numeric tables. Each character's ASCII code acts like stored data.

6. Forgetting that putchar(10) means newline

This is valid:

putchar(10);

But beginners should prefer:

putchar('\n');

because it is clearer.

7. Trying to learn obfuscated code without rewriting it

Best practice when reading code like this:

  • isolate subexpressions
  • rewrite them in normal syntax
  • name intermediate values
  • test assumptions with small examples

For example:

int next = -~_;
int stop = (_ ^ 448) == 0;

Comparisons

Obfuscated style vs readable style

TopicObfuscated versionReadable version
Increment-~xx + 1 or ++x
Equality checkx ^ 448 equals 0x == 448
Conditional executioncond && action()if (cond) action();
Newline10'\n'
Array access7[s]s[7]
Space or !`32bit`

Recursion vs loop

ApproachGood forIn this program
RecursionElegant definitions, tree structuresUsed as a disguised loop
for loopCounting through positionsWould be clearer
while loopOpen-ended iterationPossible, but less natural here

Packed bitmaps vs explicit character drawings

ApproachProsCons
Packed bitsCompactHard to read
2D arrays of 0/1Easy to understandMore verbose
Literal ASCII art templatesVery readableLess flexible

Old C style vs modern C style

FeatureOld style used hereModern style
Return typeimplicit intexplicit int
Function declarationscan be omittedinclude headers
Main signaturemain(_)int main(void)
Readabilityintentionally lowstrongly preferred
Take Quiz

Cheat Sheet

Quick reference

Weird syntax used in sykes2.c

-~x        // x + 1
x ^ y      // bitwise XOR
a && b     // evaluate b only if a is true
cond ? A : B
7[s]       // same as s[7]
32 | bit   // 32 if bit=0, 33 if bit=1

Useful facts

  • __TIME__ is a string literal like "14:53:07"
  • putchar('\n') and putchar(10) both print a newline
  • a[b] means *(a + b)
  • x >> n & 1 extracts one bit

Structural constants in this program

  • 8 characters in __TIME__
  • 8 columns per character block
  • 64 columns per line
  • 7 lines total
  • 448 total output positions

Readable rewrites

_ ^ 448 && main(-~_);

becomes

if (_ != 448) main(_ + 1);
7[__TIME__ - _ / 8 % 8]

becomes

__TIME__[7 - (_ / 8 % 8)]
32 | bit

becomes

bit ? '!' : ' '

Edge cases to remember

  • This code depends on old C rules and permissive compilation
  • Modern compilers may warn heavily
  • Do not copy this style into production code
  • The strings in the expression are data tables, not normal text

FAQ

Why does 7[__TIME__ - n] work in C?

Because array indexing is defined as pointer arithmetic: a[b] means *(a + b). So 7[s] is the same as s[7].

What does -~_ mean in C?

It is a trick for _ + 1. The bitwise NOT and unary minus combine to produce the next integer.

Why does the program use recursion instead of a loop?

Mostly for obfuscation. It behaves like a loop over 448 output positions, but recursion makes the code look stranger.

What is __TIME__ in C?

__TIME__ is a predefined macro that expands to the compilation time as a string in the form "hh:mm:ss".

Why does the code print ! instead of solid blocks?

Because it maps a single extracted bit to either ASCII 32 (' ') or ASCII 33 ('!').

Is this valid modern C?

Not really as good modern style. It may still compile with some compilers, but it relies on outdated features like implicit int and missing function declarations.

What are the strange string literals doing?

They act as compact lookup tables. Their character codes are used as numeric bit patterns for drawing the digits and colons.

Why are there 448 positions?

Because the output is a 7-row grid with 64 positions per row: 7 * 64 = 448.

Take Quiz

Mini Project

Description

Build a small C program that prints the compile time (__TIME__) as large text using a readable 2D font table. This project demonstrates the same core idea as sykes2.c—turning a string into banner output—but without obfuscation. You will practice loops, indexing, compile-time macros, and simple bitmap rendering.

Goal

Create a readable C program that prints __TIME__ in a 7-row block font using spaces and ! characters.

Requirements

  1. Use __TIME__ as the source text.
  2. Print the output as 7 rows of large characters.
  3. Support digits 0 through 9 and the colon :.
  4. Use loops instead of recursion.
  5. Print spaces for empty pixels and ! for filled pixels.
Take Quiz

Keep learning

Related questions

View more