Делаю так давно. Полёт нормальный.
///////////////////////////////////////////////////////////////////////////////
/* Макросы, обеспечивающие доступ к отдельным фрагментам переменных (массивов).
Фрагменты лево и праводопустимые.
Значения адреса "A" и байтового сдвига "S", желательно, вычисляемые на этапе
компиляции. (использовались для CodeVisionAVR V1.25.9 и Borland C++Builder)
Примеры:
long L;
putchar(MU1(&L,0));
putchar(MU1(&L,1));
putchar(MU1(&L,2));
putchar(MU1(&L,3));
MU1(&L,0) = getchar();
MU1(&L,1) = getchar();
MU1(&L,2) = getchar();
MU1(&L,3) = getchar();
char C[4];
L = MU4(C,0);
MU4(C,0) = L;
short S[4] = {0x2010, 0x4030, 0x6050, 0x8070};
MU1(S,3) -> 0x40
MU1(S,4) -> 0x50
MU1(S+1,3) -> 0x60
MU1(S+1,4) -> 0x70
MU2(S+1,3) -> 0x7060
MU2(S+1,4) -> 0x8070
MU4(S+1,1) -> 0x70605040
*/
#define MU1(A,S) (*((unsigned char*)(A)+(S)))
#define MS1(A,S) (*((signed char*)(A)+(S)))
#define MU2(A,S) (*(unsigned short*)((char*)(A)+(S)))
#define MS2(A,S) (*(signed short*)((char*)(A)+(S)))
#define MU4(A,S) (*(unsigned long*)((char*)(A)+(S)))
#define MS4(A,S) (*(signed long*)((char*)(A)+(S)))
#ifdef __CODEVISIONAVR__
// Для EEPROM
#define EU1(A,S) (*((eeprom unsigned char*)(A)+(S)))
#define ES1(A,S) (*((eeprom signed char*)(A)+(S)))
#define EU2(A,S) (*(eeprom unsigned short*)((eeprom char*)(A)+(S)))
#define ES2(A,S) (*(eeprom signed short*)((eeprom char*)(A)+(S)))
#define EU4(A,S) (*(eeprom unsigned long*)((eeprom char*)(A)+(S)))
#define ES4(A,S) (*(eeprom signed long*)((eeprom char*)(A)+(S)))
// Для FLASH
#define FU1(A,S) (*((flash unsigned char*)(A)+(S)))
#define FS1(A,S) (*((flash signed char*)(A)+(S)))
#define FU2(A,S) (*(flash unsigned short*)((flash char*)(A)+(S)))
#define FS2(A,S) (*(flash signed short*)((flash char*)(A)+(S)))
#define FU4(A,S) (*(flash unsigned long*)((flash char*)(A)+(S)))
#define FS4(A,S) (*(flash signed long*)((flash char*)(A)+(S)))
#endif