It is a preprocessing operator formally known as "Stringification Operator" or "Stringfication Operator".
It is used in the body of a macro for the purpose of informing the preprocessor that the macro parameter must be converted into a string.
Basically, the preprocessor will put the macro parameter in double quotes after being replaced in the macro body.
Follow a practical example as a demonstration:
#include <stdio.h>
#define debug_ptr(x)     printf("%s => %p\n", #x, x )
#define debug_int(x)     printf("%s => %d\n", #x, x )
#define debug_bool(x)    printf("%s => %s\n", #x, (x) ? "TRUE" : "FALSE" )
int foobar(int x)
{
    return x * 2;
}
int main(void)
{
    int a = 123;
    int b = 321;
    debug_ptr(&a);
    debug_int(b);
    debug_bool(a > b);
    debug_int(foobar(a));
    return 0;
}
After the pre-processing step, code macros would be expanded to something like:
#include <stdio.h>
int foobar(int x)
{
    return x * 2;
}
int main(void)
{
    int a = 123;
    int b = 321;
    printf("%s => %p\n", "&a", &a )
    printf("%s => %d\n", "b", b )
    printf("%s => %s\n", "a > b", (a > b) ? "TRUE" : "FALSE" )
    printf("%s => %d\n", "foobar(a)", foobar(a) )
    return 0;
}
Exit:
&a => 0x7ffee3284a98
b => 321
a > b => FALSE
foobar(a) => 246