您的位置:首页 > 其它

判断系统大小端方法分析与总结

2011-03-09 15:44 281 查看
2011-03-09 wcdj



问题

:如何用程序确认当前系统的存储模式(大端还是小端)?写一个C函数,若处理器是Big-endian的,则返回0;若是Little-endian的,则返回1。

情况1:利用数组类型

#include <cstdio>
int checkSystem()
{
	char s[]="1000";
	return (s[0]=='1');
}
int main()
{
	checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n");
	return 0;
}



情况2:利用位移运算

int i = 1;
if(1>>32 == 0)
      cout<<"小端模式"<<endl;
else
      cout<<" 大端模式"<<endl;




上述方法正确吗?要理解为什么不正确?



因为不要在数值上做文章,而大小端是严格与内存挂钩的东西。如果int a=1; 那么a&1==1一定成立,因为这是从数值角度运算的,已经给用户屏蔽掉了大小端的问题。一定要int a=1; *((char*)(&a)) == 1 ,这样判断才有效。

下面总结一些有效的方法。



方法1:利用union类型 —— 可以利用union类型数据的特点:所有成员的起始地址一致。


#include <cstdio>
int checkSystem()
{
	union check
	{
		int i;
		char ch;
	}c;
	c.i=1;
	return (c.ch==1);
}
int main()
{
	checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n");
	return 0;
}





方法2:对int强制类型转换

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int i = 1;
	(*(char *)&i == 1) ? printf("Little-endian/n") : printf("Big-endian/n");
	system("pause");
	return 0;
}




方法3:使用union和宏定义

#include<stdio.h>
#include<stdlib.h>
static union
{
	char a[4];
	unsigned long ul;
}endian = {{'L', '?', '?', 'B'}};
#define ENDIAN ((char)endian.ul)

int main()
{
	printf("%c/n", ENDIAN);
	system("pause");
	return 0;
}




补充:

大小端模式对union类型数据的影响。

#include <cstdio>
union
{
	int i;
	char a[2];
}*p, u;
int main()
{
	p=&u;
	p->a[0]=0x39;
	p->a[1]=0x38;
	printf("%x/n",p->i);// 3839 (hex.)
	printf("%d/n",p->i);// 111000 00111001=14393 (decimal)
	return 0;
}





分析如下图所示:

高地址 低地址

—— —— —— —— int

0 | 0 | 56 | 57

—— —— —— ——

—— —— char

56 | 57

—— ——

这里需要考虑存储模式:大端模式和小端模式。

大端模式(Big-endian):数据的低字节存放在高地址中。

小端模式(Little-endian):数据的低字节存放在低地址中。

union型数据所占的空间等于其最大的成员所占的空间,对union型成员的存取都是相对于该联合体基地址的偏移量为0处开始,即,联合体的访问不论对哪个变量的存取都是从union的首地址位置开始。因此,上面程序输出的结果就显而易见了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: