/* * playground_05-25-2011.c * * * Playing around with unions and macros, and how both * of these things look in the memory * */ #include #include #define EXP(base, exp, ret) do { \ int i; \ int acc = 1; \ for (i = 0; i < exp; i++) \ acc *= base; \ ret = acc; \ } while(0) \ #define MUL(base, mult, ret) do { \ int i; \ int acc = 0; \ for (i = 0; i < mult; i++) \ acc += base; \ ret = acc; \ } while(0) \ /* trace a variable, requires ANSI compliant compiler */ #define TRACE(var, fmt) \ printf("TRACE: " #var " = " #fmt ", %s:%d\n", var, __FILE__, __LINE__) #pragma pack(1) struct UART_tag { union { struct { uint32_t baud_rate; /* bits [0:31] */ uint8_t tx_en : 1; uint8_t rx_en : 1; uint8_t parity : 1; /* bit [34], 35th */ uint32_t : 29; } B; uint64_t R; } SET; }; typedef struct UART_tag UART_t; void UART_info(UART_t *dev) { printf("baud rate: %u\n" "tx enabled: %s\n" "rx enabled: %s\n" "parity enabled: %s\n", dev->SET.B.baud_rate, dev->SET.B.tx_en ? "yes" : "no", dev->SET.B.rx_en ? "yes" : "no", dev->SET.B.parity ? "yes" : "no"); } void dumpHex(UART_t *p, unsigned int sz) { int i; for (i = 0; i < sz; i++) { if (i % 4 == 0) printf("%s0x%08x: ", i == 0 ? "" : "\n", i); printf(" 0x%02x", ((unsigned char *) p)[i] ); } printf("\n\n"); } int main(int argc, char **argv) { /* assigning a struct within the union */ puts("\t assigning a struct within the union"); UART_t myUart; myUart.SET.R = 0; myUart.SET.B.baud_rate = 19200; myUart.SET.B.tx_en = 1; myUart.SET.B.rx_en = 1; myUart.SET.B.parity = 0; UART_info(&myUart); puts(""); puts("\t this is how UART_t looks in the memory"); dumpHex(&myUart, sizeof(UART_t)); /* disable a flag within the struct */ puts("\t disable a flag within the struct"); myUart.SET.B.tx_en = 0; UART_info(&myUart); puts(""); /* modifying the whole structure at once */ puts("\t modifying the whole structure at once"); myUart.SET.R = 0; UART_info(&myUart); puts(""); /* enable the parity bit */ myUart.SET.R |= (uint64_t) \ ((uint64_t) 1 << (64 - 30)); /* this is inverted compared * to how it would be done on * a register */ puts("\t setting the parity bit to ON using logical OR operator"); UART_info(&myUart); puts(""); printf("size of UART_t is: %lu bytes\n", sizeof(UART_t)); printf("size of UART_tag is: %lu bytes\n", sizeof(myUart.SET.B)); int x; EXP(2, 20, x); printf("a megabyte is %d bytes\n", x); int y; MUL(x, 4, y); printf("4 megabytes is %d bytes\n", y); /* endianess */ int z = 1; if (*((unsigned char *) &z) == 1) puts("machine has a little-endian byte ordering"); else puts("machine has a big-endian byte ordering"); TRACE(y, %d); return 0; }