+#define external_array(type, name) \ + ({ \ + extern type name[]; \ + type *name_ptr = name; \ + asm ("" : "+r" (name_ptr)); \ + name_ptr; \ + })
I've had to pull similar tricks to persuade GCC to generate the code I wanted (in my case, it was optimization: "evaluate it in this order, damn it!"), and I prefer to use the asm itself with overlapping operands to do the assignment. #define external_array(type, name) \ ({ \ extern type name[]; \ type *name_ptr; asm ("" : "=g" (name_ptr) : "0" (name)); \ name_ptr; \ }) You could define a wrapper if you like, something like /* * Assign dst = src, but prevent the compiler from inferring anything * about the assigned value, so it can't do any unwanted optimization. */ #define blind_assign(dst,src) asm("" : "=X" (dst) : "0" (src)) In case it helps, here's a list of architecture-independent operand constraints (that I think is exhaustive, but I'm not 100% sure): r - general-purpose register f - floating-point register m - memory o - offsettable memory (excluding pre/post inc/decrement modes) i - immediate g - "general", any of the above X - "wildcard". This matches anything at all, including special-purpose registers that are not included in "r".