【轉】玩轉嵌入式(公眾號)
在入門單片機時,想必大家都都會遇到一下這種情況
unsigned char a = 0x12;
unsigned char b = 0x34;
unsigned int c = 0;
如何把兩個8位數據和在一起變成16位數據呢?
一般情況下大家都會這樣做,我最初是也是這么做的
方法1 【使用移位指令】
int c = (a<<8)|b;
方法2 【使用指針】
unsigned char *cptr;
cptr = (unsigned char*)(&d);
cptr[0] = a;
cptr[1] = b;
方法3 【強制指針類型轉換】
*((unsigned char*)(&d)) = a;
*((unsigned char*)(&d)+1) = b;
或
((unsigned char*)(&d))[0] = a;
((unsigned char*)(&d))[1] = b;
以上這三種方法都是沒有錯誤的,但在keil編譯器中編譯出的結果是不一樣的。第三種方法編譯出的代碼會更簡潔
今天就交給大家第4種方法
方法4 【聯合體】
typedef union{
unsigned int i;
unsigned char c[2];
}u_int;
unsigned char dH = 0x11, dL=0x22;
unsigned int d;
u_int ud;
ud.c[0] = dH;
ud.c[1] = dL;
d = ud.i;
此時d = 0x1122;
這里就是利用了聯合體union的特性來實現把兩個8位數據合並成一個16位數據的方法。在C語言里操作指針最容易出現錯誤,所以在遇到這樣類似的問題大家不妨使用聯合體的方式進行處理數據,既不容易出現錯誤,生成的代碼又簡潔。
測試代碼
1 #include "stdio.h" 2 3 typedef unsigned char uint8_t; 4 typedef unsigned short uint16_t; 5 typedef unsigned int uint32_t; 6 7 8 uint8_t a = 0x12; 9 uint8_t b = 0x34; 10 uint16_t c; 11 12 /* 使用移位轉換類型 */ 13 void use_shift(uint16_t *val) 14 { 15 *val = (a<<8) | b; 16 } 17 18 /* 使用指針轉換類型 */ 19 void use_point(uint16_t *val) 20 { 21 uint8_t *p; 22 23 p = (uint8_t *)val; 24 p[0] = b; 25 p[1] = a; 26 } 27 28 /* 強制指針轉換類型 */ 29 void force_point_convert(uint16_t *val) 30 { 31 #if 0 32 *((uint8_t *)val) = b; 33 *((uint8_t *)val + 1) = a; 34 #else 35 ((uint8_t *)val)[0] = b; 36 ((uint8_t *)val)[1] = a; 37 #endif 38 } 39 40 /* 使用共用體轉換類型 */ 41 typedef union 42 { 43 uint16_t int16; 44 uint8_t char8[2]; 45 } CVR_u; 46 CVR_u Obj; 47 48 void use_union(CVR_u *p) 49 { 50 p->char8[0] = b; 51 p->char8[1] = a; 52 } 53 54 int main(void) 55 { 56 c = 0; 57 use_shift(&c); 58 printf("c1= %#X\n", c); 59 60 c = 0; 61 use_point(&c); 62 printf("c2= %#X\n", c); 63 64 c = 0; 65 force_point_convert(&c); 66 printf("c3= %#X\n", c); 67 68 c = 0; 69 use_union(&Obj); 70 c = Obj.int16; 71 printf("c4= %#X\n", c); 72 73 return 0; 74 }