#
is the "stringizing" operator; it turns its argument into a string literal.
##
is the "token-pasting" operator; it joins its two arguments into a single token, not necessarily a string literal.
An example:
#include
#define foo(m, n) m ## n
int main(void) {
char *kl = "token pasting";
printf("%s\n", foo(k, l));
}
which prints:
token pasting