This is the solution I came across when implementing a couple of alternatives for accessing data fields:
// #define USE_MEMCPY // #define USE_PACKED #ifdef __cplusplus template <typename T> void SET(T *__attribute__((may_alias)) p, T val) { *p=val; } template <typename T> T GET(T *__attribute__((may_alias)) p) { return *p; } #else #ifdef USE_MEMCPY #include <string.h> #define _SET(p,val,line) \ ({ typeof(val) _temp_##line = (val); \ memcpy((void*)(p),(void*)&_temp_##line,sizeof(_temp_##line)); }) #define _GET(p,line) \ ({ typeof(*(p)) _temp_##line; \ memcpy((void*)&_temp_##line,(void*)(p),sizeof(_temp_##line)); \ _temp_##line; }) #define SET(p,val) _SET(p,val,__LINE__) #define GET(p) _GET(p,__LINE__) #else /* no memcpy */ #ifdef USE_PACKED #define SET(p,val) (((struct { typeof(val) x __attribute__((packed)); } __attribute__((may_alias))*)p)->x=(val)) #define GET(p) (((struct { typeof(*p) x __attribute__((packed)); } __attribute__((may_alias))*)p)->x) #else #define SET(p,val) (*((typeof(val) __attribute__((may_alias))*)p)=(val)) #define GET(p) (*((typeof(*p) __attribute__((may_alias))*)p)) #endif #endif #endif
Then I can write a function like this:
int q(int *p) { SET(p,GET(p)+12); return p[0]; }
source share