Это UB.
Подъем char * foo_buf[20];
не должен давать вам худший код. Все локальные функции функции, вероятно, в любом случае будут размещены наверху, и компиляторы вполне способны устранить локальные элементы, которые никогда не используются.
Попробуйте скомпилировать:
#define UP 0
#define CONST 1
#include <stdio.h>
#if CONST
#define SOME_MACRO() 0
#else
int SOME_MACRO(void);
#endif
int some_global;
void some_func(void) {
const char * foo;
#if UP
char foo_buf[20]; //fixed from char *foo_buf[20];
#endif
if (SOME_MACRO()) {
#if !UP
char foo_buf[20]; //fixed from char *foo_buf[20];
#endif
snprintf(foo_buf,sizeof(foo_buf),"blah_%d",some_global);
foo = foo_buf;
} else {
foo = "some constant string";
}
// do a bunch of other stuff here...
printf("%s\n", foo);
}
с CONST, установленным в 0 или 1, а затем с изменением ВВЕРХ на значение от 0 до 1.
Когда gcc, clang или icc перемещают объявление (изменяя UP
), не имеет значения даже при -O0
: https://gcc.godbolt.org/z/z9jnQD.