https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38354
--- Comment #11 from Adam Warner <adam at consulting dot net.nz> --- Thank you Joseph for clarifying in Comment 10 why this should be considered an enhancement request. It would be non-trivial to change the model of what GNU C considers a constant expression and code relying on an enhanced model of constant expression is likely to be incompatible with other compilers. I now have a 100% efficient fairly portable workaround in a few lines of bash scripting. Here is an example lookup_table.c: #include <stdint.h> #include <stdio.h> #include "lookup_table.h" void fn0(void) {printf("fn0\n");} void fn1(void) {printf("fn1\n");} void fn2(void) {printf("fn2\n");} void fn3(void) {printf("fn3\n");} int main(void) { for (int i=0; i<4; ++i) ((void (*)(void)) (uint64_t) lookup_table[i])(); return 0; } To compile/execute the C code run this bash script named lookup_table.sh: #!/bin/bash if [[ ! -f lookup_table.h ]]; then echo "uint32_t lookup_table[4];" >> lookup_table.h; fi gcc -std=gnu11 -O3 lookup_table.c -o lookup_table mv -f lookup_table.h lookup_table.h.old echo "uint32_t lookup_table[] = {" > lookup_table.h objdump -d -m i386:x86-64 lookup_table | grep '<fn' | sed 's/^0/0x0/' | sed 's/ .*/,/' >> lookup_table.h echo "};" >> lookup_table.h diff -su lookup_table.h.old lookup_table.h && ./lookup_table || ./lookup_table.sh Example output: $ ./lookup_table.sh --- lookup_table.h.old 2014-09-10 13:35:03.162644646 +1200 +++ lookup_table.h 2014-09-10 13:35:03.222648312 +1200 @@ -1 +1,6 @@ -uint32_t lookup_table[4]; +uint32_t lookup_table[] = { +0x0000000000400530, +0x0000000000400540, +0x0000000000400550, +0x0000000000400560, +}; Files lookup_table.h.old and lookup_table.h are identical fn0 fn1 fn2 fn3 The lookup table functions must share a unique prefix. If the new lookup_table.h matches the old lookup_table.h then the binary is internally consistent and ready for execution. There is no additional overhead in the final binary: 0000000000400410 <main>: 400410: 53 push rbx 400411: bb e0 09 60 00 mov ebx,0x6009e0 400416: 8b 03 mov eax,DWORD PTR [rbx] 400418: 48 83 c3 04 add rbx,0x4 40041c: ff d0 call rax 40041e: 48 81 fb f0 09 60 00 cmp rbx,0x6009f0 400425: 75 ef jne 400416 <main+0x6> 400427: 31 c0 xor eax,eax 400429: 5b pop rbx 40042a: c3 ret In this example the lookup table has been mapped into memory at address 0x6009e0. There is a 32-bit load for each function call. No code is required to populate the lookup table at run time. No internal run time checks are required to ensure the lookup table and function addresses match. This is a perfectly efficient workaround that is superior to the C++ approach.