Using state transitions to filter C comments
In all, this looks like pretty solid code.  I have just a few suggestions that may help you improve your code.

Use an enum for related constants

The states are all related and not just standalone constants.  For that reason, I'd recommend encapsulating them all in an enum:

enum { NORMAL, SINGLE_QUOTE, DOUBLE_QUOTE, SLASH, MULTI_COMMENT, INLINE_COMMENT, STAR } state_e;


Restructure or comment to make the code easier to read

The most significant feature in the code is a state machine.  In order to understand a state machine, I typically need to know what's being processed (an input C program), what the states are (which are enumerated) and how the code transitions from state to state.  The last bit is the part that is a little tough to decipher.  It's probably mostly right, but it's hard to decode.  For instance, see how long it takes you to answer the questions, "How does the code enter the SLASH state?", "How does it leave the SLASH state?"

Don't forget about line continuation

The \ character is a line continuation character in C.  One effect it can have that affects this program is to continue a single-line comment:

// BAD is never defined \
#define BAD 1


Don't forget about trigraphs

Many people either don't use or don't know about trigraphs but they exist and, for better or worse, are still part of the language. This affects this particular program because the ??/ is the trigraph for \ which is the line continuation character.  Related to the preceding comment, BAD is never defined in this code fragment:

// are you surprised??/
#define BAD 1