>effectively don't they do the same thing?
Somewhat. The define is a textual replacement. Anywhere you say X, it's turned into 100 before the code is compiled. Y, on the other hand, is an actual object that the compiler will recognize. You should choose the latter simply because there's fewer surprises with typing and the debugger can be more informative with an object than a literal value.

really you should not.
a constant whose value is known at compile time
a. may (would) be placed into memory with read-only access by the compiler if it has a static storage class.
b. the compiler can (should) treat such a contant as if it is a literal constant. eg.