The absence of preprocessor directives does not guarantee anything but the absence of preprocessor directives.
You can still manually add data types and function prototypes for any library functions that interest you. If you are familiar with the base platform, you can completely bypass the standard library and make system calls directly.
I once saw code (possibly for IOCCC) that used an unsigned char array to store raw opcodes, and then used the punning type to treat it as a function, something like
unsigned char instr[] = {0x00, 0x12, 0x33, ...}; void (*foo)(void) = (void (*)(void)) instr; foo();
Note that this is due to undefined behavior and a lot of unpromising assumptions, and I'm not even sure that this approach will work anymore. But if this happened, it is not something that would be easy to catch with a simple source scan.
EDIT
I found the code I was thinking about - it has been an IOCCC entry since 1984. This does not work as I described, though. Hey, I'm getting old, and the material doesn't stick to my brain like before.
short main[] = { 277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800, -113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004, 14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9, 4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419, 0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0, 4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#', 0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712, 'p', 072163, 'r', 29303, 29801, 'e' };
Here's an explanation :
The Grand Prize:
Sjoerd Mullender & Robbert van Renesse
Without question, this C program is the most obfuscated C program that
has ever been received! Like all great contest entries, they result
in a change of rules for the following year. To prevent a flood of
similar programs, we requested that programs be non machine specific.
This program was selected for the 1987 t-shirt collection.
NOTE: If your machine is not a Vax-11 or pdp-11, this program will
not execute correctly. In later years, machine dependent
code was discouraged.
The C startup routine (via crt0.o) transfers control to a location
named main. In this case, main just happens to be in the data area.
The array of shorts, which has been further obfuscated by use of
different data types, just happens to form a meaningful set of PDP-11
and Vax instructions. The first word is a PDP-11 branch instruction
that branches to the rest of the PDP code. On the Vax main is called with
the calls instruction which uses the first word of the subroutine as a
mask of registers to be saved. So on the Vax the first word can be anything.
The real Vax code starts with the second word. This small program
makes direct calls to the write () Unix system call to produce a
message on the screen. Can you guess what is printed? We knew you
couldn't! :-)
Copyright (c) 1984, Landon Curt Noll.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
Again, I don't know if this trick will work on any modern desktop OS, but it would be interesting to know.