No hay ninguna diferencia, lo que haces con un #define es declarar constantes. Ahora, esas constantes pueden ser un valor o una expresión.
ERROR Si la hay, y es ENORME.
define: lo que esté despues de, por así decirlo, la etiqueta, se EMPOTRA directamente en el código, por el preprocesador, no se hace comprobación de tipos ni nada por el estilo, simplemente se sustituye, y ya.
Ejemplo:
#define cuadrado((a)) (a)*(a)
con el siguiente ejemplo:
i=4;
cuadrado(i++)
Resultado? 16, si, valor de la i=5? NO i=6. ¿WTF? Pensarán algunos.
Porque el preprocesador lo sustituye como:
i=4
(i++)*(i++)
Y por precedencia de operadores, se realiza la multiplicación, y luego los post-incrementos
Por otro lado, un define NO ocupa más memoria que la que ocupe el código definido y dicha memoria será ocupada en el espacio dedicado a código, mientras que una constante, es una variable, y que por tanto, ocupará su espacio en el segmento de memoria dedicado a variables.
Por otro lado, utilizando el ejemplo del cuadrado, mirad que pasa si hacéis esto:
cuadrado(cuadrado(i)*cuadrado(i))
Lo ideal sería suponer una implementación de este estilo:
res1=resultado_cuadrado(i)*resultado_cuadrado(i)
cuadrado(res1)
Pero, con los defines, al tratarse de código empotrado, se traduce como(es posible que me deje algo, pero básicamente es un infierno de calculo):
((i*i)*(i*i))*((i*i)*(i*i))
Por qué? Porque primero, traduce el cuadrado de i en i*i, y luego, la multiplicación de cuadrados en (i*i)*(i*i) PERO como luego eso se lo pasamos como "argumento", y nuestro define, coge dicho argumento y lo multiplica por si mismo, tenemos la tira infernal de arriba.
Los defines (macros) son peligrosos.