Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a GNU C macro envSet(name), what does (void) "" name mean?

I came across this syntax today and couldn't work out what it meant:

// Uses the GNU C statement expression extension
#define envSet(name) ({ \
static int initialised; \
static bool set; \
(void) "" name; \
if (!initialised || !g_cacheEnv) { \
    const char *value = getenv(name); \
    set = value != NULL; \
    initialised = true; \
} \
set; \
})

The specific line I cannot understand is:

(void) "" name; \

Could somebody please shed some light on this?

like image 541
OMGtechy Avatar asked Sep 30 '16 13:09

OMGtechy


3 Answers

It looks like a way to statically ensure that name is a string literal and not some other type.

If you do (void)"" "hello"; then it is a valid C expression.

But if you do something like (void)"" 1; then you get a syntax error.

like image 179
Lundin Avatar answered Nov 15 '22 07:11

Lundin


Two consecutive string literals are concatenated. Presumably it's checking whether name is a string literal. If it isn't, the compiler will report an error.

(void) cast will supress warnings like "statement with no effect".

like image 33
milleniumbug Avatar answered Nov 15 '22 06:11

milleniumbug


Looking at the code, I believe the purpose is to have it call getenv the first time it is called, cache the result, and then after that use the cached result without having to call getenv anymore. If getenv is used with a string literal, then all subsequent calls will ask for the same environment variable; if nothing could change that environment variable they would consequently return the same result. If the code were given a pointer to a string that subsequently changed, the cached result would likely not be correct for the new string, so the purpose of the "" trick is to ensure that can't happen.

Because every string literal that might be used would need to have its own static variable associated with it, the indicated code snippet cannot sensibly be made into a function. On the other hand, the amount of code needed for each repetition does seem a bit much. Further, if the same variable is tested at more than one place in the code, each could end up with its own set of variables and environment-checking code.

Depending upon how the function will be used, it may end up being much faster than code which needs to test an environmental variable every time it's called, and it may be usable from within a function that is called within a loop without advance setup (if client code called an "advance setup" function, the name lookup should be done there, eliminating the need to check within the loop to see if the lookup had been done).

like image 7
supercat Avatar answered Nov 15 '22 05:11

supercat