汉扬编程 编程大纲 C语言 机器字节序、大小端的判断与修改

C语言 机器字节序、大小端的判断与修改

一、机器字节序

1、int a = 1;

低地址 高地址

0x100 0x101 0x102 0x103

对于 int 型的整数1,对应的二进制数为:

0000 0000 0000 0000 0000 0000 0000 0001

高字节 低字节

2、我们定义一个整形变量a,假设其初始地址为0x100,结束地址为0x103,那么0x100对应

低地址,0x103对应高地址。而对于二进制数据,最前面为高字节,最后面为低字节,但

低地址存放高字节还是低字节呢?各个机器可能不同。

3、低地址存放高字节为大端;低地址存放的字节为小端;

二、那么该如何判断机器的字节序呢?

我们可以使用联合体,因为联合体的成员共用一段内存。

代码如下:

#include <stdio.h>

union test

{

short val;

char array[sizeof(short)];

};

int main()

{

union test t;

t.val = 0x0102;

if (t.array[0] == 2 && t.array[1] == 1)

{

printf("Little Endian\\n");

}

else if (t.array[0] == 1 && t.array[1] == 2)

{

printf("Big Endian\\n");

}

else

{

printf("Unkown\\n");

}

return 0;

}

三、那么如何实现大小端的转换呢?

1、使用位运算 2、移位

那么该如何移位呢?

定义一个unsigned int a;

假设a的二进制位:1011 1100 0001 1100 1110 0011 0011 0001

a & 0x0000 00ff << 24 0011 0001 0000 0000 0000 0000 0000 0000

a & 0x0000 ff00 << 8 0000 0000 1110 0011 0000 0000 0000 0000

a & 0x00ff 0000 >>8 0000 0000 0000 0000 0001 1100 0000 0000

a & 0xff00 0000 >>24 0000 0000 0000 0000 0000 0000 1011 1100

代码实例:

#include <stdio.h>

int mian()

{

unsigned int a = 1;

unsigned int b;

b = (((a & 0x000000ff) << 24) | ((a & 0x0000ff00) << 8) | ((a & 0x00ff0000) >> 8) | ((a & 0xff000000) >>24));

printf("%d\\n",b);

return 0;

}

C语言验证大小端的几个方法

大小端的问题在很多面试笔试中都会遇到,最直接的考察是,笔试的时候,让你写一个代码,如何确定当前系统是大端还是小端的。

C语言 机器字节序、大小端的判断与修改

什么是大端和小端呢?

C语言 机器字节序、大小端的判断与修改

大端: 高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。(CPU对操作数的存放方式是从高字节到低字节)

C语言 机器字节序、大小端的判断与修改

小端: 低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。(CPU对操作数的存放方式是从低字节到高字节)

C语言 机器字节序、大小端的判断与修改

假设我们的内存是这样的

C语言 机器字节序、大小端的判断与修改

C语言 机器字节序、大小端的判断与修改

我们要存一个数据 0x44332211到这块内存里面去 如果系统是小端模式的话,存储方式如下图

C语言 机器字节序、大小端的判断与修改

C语言 机器字节序、大小端的判断与修改

如果系统是大端模式的话,存储方式如下图

好了,我们既然知道了大端和小端的存储方式不同,那就可以写代码来判断当前系统的存储模式了。

方法一#include <cstdio>int main(){ int i = 1; (*(char *)&i == 1) ? printf("Little-endian\\n") : printf("Big-endian\\n"); return 0;}

指针类型转换,最后取 char * 指针的值,也就是判断 int 低地址的数据是否为1。

方法二#include <cstdio>union System{ char a; int b;};int main(){ union System s; s.b = 1; printf("0x%x\\n",&s.a); printf("0x%x\\n",&s.b); if(s.a == 1) { printf("Little-endian\\n"); } else { printf("Big-endian\\n"); } return 0;}

共用体的特点是,使用类型最大的那个类型作为共用体的大小,所以,char a 使用的是 int b的空间大小,判断 a的值,也就是判断低地址的数据值。

方法三#include<stdio.h>static union{ char a[4]; int ul;}endian = {{'L', '?', '?', 'B'}};#define ENDIAN ((char)endian.ul) int main(){ printf("%cENDIAN\\n", ENDIAN); return 0;}

宏和字符数组

方法四#include<stdio.h>int main(){ int a = 0x44332211; char *b = (char *)&a; (*b == 0x11)?printf("Little-endian\\n") : printf("Big-endian\\n"); return 0;}

直接指针操作,原理也是取 int 低地址判断里面的数据。

总结所有的判断依据都是按照上面的理论来验证的,读者们如果对代码有什么疑惑或者问题的请给我留言,我也不敢保证自己写的代码一定是正确的,几个方法也是参考网上的写法,我最喜欢还是用union来实现。如果在面试中突然不知道怎么写,我建议还是画个图出来先理解一下,这样更有利于写代码。

我原来也是上来就想把代码写出来,经过这些年的锤炼,我明白了,原理远比代码来的重要,我们学习也不要局限在某种语言上面,语言是为了实现某种需求的,C,C++,python,等等,都只是一种语言而已,说白了,就是一把刀,磨得再锋利的刀,没有猪肉来砍也只是用来观赏而已。

周末愉快~共勉~

—————END—————

扫码或长按关注

回复「 加群 」进入技术群聊

本文来自网络,不代表汉扬编程立场,转载请注明出处:http://www.hyzlch.com/mianfei/6844.html

C语言学习篇(24)——大小端模式初探

(对嵌入式的理解与C语言之间的区别)嵌入式C语言中针对大小端的处理

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

返回顶部