高低字节与数组
高低地址和高低字节都是对于大于8位数据而言,读取的数据是整个数据读取,即使是一个结构体(struct)或者联合体(union)。
比如一个uint16_t num = 0x1234的数据就需要定义一个uint8_t buffer[2], 其中:
高8位DATAH是0x12,
低8位DATAL是0x34,
通常数组开始从低字节开始,对应起来就是DATAL=buffer[0], DATAH=buffer[1]。(注:这里数组与联合体数组成员解析内存数据要避免混淆)
正常来说DATAL和DATAH地址是连续的,就可以将buffer直接存入到对应寄存器中。
对于计算机而言,计算机电路基本是不管高低字节的,都是按内存顺序处理,效率比较高(就像数组一样,都是从第0个字节开始算)。
如果计算机系统优先从高位往低位读取数据存放到内存中,那么这个排列顺序就是大端;DATAH在数组前面buffer[0],DATAL在数组后面buffer[1]
如果计算机系统优先从低位往高位读取数据存放到内存中,那么这个排列顺序就是小端;DATAL在数组前面buffer[0],DATAH在数组后面buffer[1]
地址与字节联系在一起还有大小端机器的存储方式。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdint.h> typedef union { uint16_t dat; uint8_t buf[sizeof(uint16_t)]; } MEM_DAT; int isBigEndian(void) { int result = 0; uint64_t iSize = sizeof(uint16_t); if (iSize == 2) { MEM_DAT endian = {0}; /* Always store from the low address. */ endian.dat = 0x0001; /* low byte;0x01, high byte:0x00 */ #if 0 uint8_t buffer[sizeof(uint16_t)] = {0}; memcpy(buffer, &endian.dat, sizeof(uint16_t)); /* buffer[0] = 0x01; // always low byte */ printf("buffer:[%x], [%x]\n", buffer[0], buffer[1]); #endif if (endian.buf[0] == 0x01 && endian.buf[1] == 0x00) { /* Low addr -> Low byte */ printf("little endian.\n"); result = 0; } else if (endian.buf[0] == 0x00 && endian.buf[1] == 0x01) { /* Low addr -> High byte */ printf("big endian.\n"); result = 1; } else { printf("unkown data.\n"); result = -1; } } else { printf("unkown size(%lu).\n", iSize); result = -1; } return result; } int main(int argc, char *argv[]) { uint32_t iNum = 0x12345678; // 0x1........8: byte High -> Low uint8_t buffer[4] = {0}; // b[0] -> b[3]: byte Low -> High memcpy(buffer, &iNum, sizeof(buffer)); // buffer[0] = 0x78; 0111 1000 Bit 7:0 // buffer[1] = 0x56; 0101 0110 Bit 15:8 // buffer[2] = 0x34; 0011 0100 Bit 23:16 // buffer[3] = 0x12; 0001 0010 Bit 31:24 printf("buffer:[%x],[%x],[%x],[%x]\n", buffer[0], buffer[1], buffer[2], buffer[3]); isBigEndian(); return (EXIT_SUCCESS); }