Question
How sykes2.c Works: Explaining an Obfuscated C Program That Prints __TIME__
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), so7[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:
- Counts through positions in a 7-row text grid
- Decides whether the current position should be a newline or a visible character
- Maps each text cell to one of the 8 characters in
__TIME__ - Looks up the correct segment/pixel for that character
- 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(_)meansmainhas an implicit return type ofint_has no declared type, so it also defaults tointputcharis 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?
- Is this the end of the line? Print
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
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_ ^ 448is zero only when_ == 448A && BevaluatesBonly ifAis 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:
| Index | Character |
|---|---|
| 0 | hour tens |
| 1 | hour ones |
| 2 | : |
| 3 | minute tens |
| 4 | minute ones |
| 5 | : |
| 6 | second tens |
| 7 | second 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 | 0is ASCII 32, which is' '32 | 1is 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:
~xis bitwise NOT-~xis a well-known trick forx + 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:
64columns per row7rows64 * 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
--_ % 64is 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:
- Determine current row and column
- Map the column to one of the 8 characters in
__TIME__ - Read the actual time character, such as
'4'or':' - Convert that character into an index into encoded font data
- Extract one bit for the current pixel
- 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.
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
| Topic | Obfuscated version | Readable version |
|---|---|---|
| Increment | -~x | x + 1 or ++x |
| Equality check | x ^ 448 equals 0 | x == 448 |
| Conditional execution | cond && action() | if (cond) action(); |
| Newline | 10 | '\n' |
| Array access | 7[s] | s[7] |
Space or ! | `32 | bit` |
Recursion vs loop
| Approach | Good for | In this program |
|---|---|---|
| Recursion | Elegant definitions, tree structures | Used as a disguised loop |
for loop | Counting through positions | Would be clearer |
while loop | Open-ended iteration | Possible, but less natural here |
Packed bitmaps vs explicit character drawings
| Approach | Pros | Cons |
|---|---|---|
| Packed bits | Compact | Hard to read |
2D arrays of 0/1 | Easy to understand | More verbose |
| Literal ASCII art templates | Very readable | Less flexible |
Old C style vs modern C style
| Feature | Old style used here | Modern style |
|---|---|---|
| Return type | implicit int | explicit int |
| Function declarations | can be omitted | include headers |
| Main signature | main(_) | int main(void) |
| Readability | intentionally low | strongly preferred |
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')andputchar(10)both print a newlinea[b]means*(a + b)x >> n & 1extracts 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.
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
- Use
__TIME__as the source text. - Print the output as 7 rows of large characters.
- Support digits
0through9and the colon:. - Use loops instead of recursion.
- Print spaces for empty pixels and
!for filled pixels.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.