zoukankan      html  css  js  c++  java
  • 判断系统大小端方法分析与总结

    转自http://blog.csdn.net/delphiwcdj/article/details/6234383

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

    情况1:利用数组类型

    1. #include <cstdio>  
    2. int checkSystem()  
    3. {  
    4.     char s[]="1000";  
    5.     return (s[0]=='1');  
    6. }  
    7. int main()  
    8. {  
    9.     checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n");  
    10.     return 0;  
    11. }  

    情况2:利用位移运算

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

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

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

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

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

    1. #include <cstdio>  
    2. int checkSystem()  
    3. {  
    4.     union check  
    5.     {  
    6.         int i;  
    7.         char ch;  
    8.     }c;  
    9.     c.i=1;  
    10.     return (c.ch==1);  
    11. }  
    12. int main()  
    13. {  
    14.     checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n");  
    15.     return 0;  
    16. }  

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

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

    方法3:使用union和宏定义

    1. #include<stdio.h>  
    2. #include<stdlib.h>  
    3. static union  
    4. {  
    5.     char a[4];  
    6.     unsigned long ul;  
    7. }endian = {{'L', '?', '?', 'B'}};  
    8. #define ENDIAN ((char)endian.ul)  
    9.   
    10. int main()  
    11. {  
    12.     printf("%c/n", ENDIAN);  
    13.     system("pause");  
    14.     return 0;  
    15. }  

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

    1. #include <cstdio>  
    2. union  
    3. {  
    4.     int i;  
    5.     char a[2];  
    6. }*p, u;  
    7. int main()  
    8. {  
    9.     p=&u;  
    10.     p->a[0]=0x39;  
    11.     p->a[1]=0x38;  
    12.     printf("%x/n",p->i);// 3839 (hex.)  
    13.     printf("%d/n",p->i);// 111000 00111001=14393 (decimal)  
    14.     return 0;  
    15. }  

    分析如下图所示:
    高地址        低地址
    —— —— —— ——   int
    0   |   0   |  56  |  57   
    —— —— —— ——
                   —— ——   char
                    56  |   57
                   —— ——     
    这里需要考虑存储模式:大端模式和小端模式。
    大端模式(Big-endian):数据的低字节存放在高地址中。
    小端模式(Little-endian):数据的低字节存放在低地址中。
    union型数据所占的空间等于其最大的成员所占的空间,对union型成员的存取都是相对于该联合体基地址的偏移量为0处开始,即,联合体的访问不论对哪个变量的存取都是从union的首地址位置开始。因此,上面程序输出的结果就显而易见了。

  • 相关阅读:
    cs ip 通过jmp转移命令间接赋值。无法直接对其赋值。
    8086 cpu为什么要把段地址*16+偏移量形成物理地址呢?
    保护模式和实模式的区别
    计算机的内存是以字节为单位的, 这个认知很重要。
    计算机的内存是以字节为单位的。
    一个字 word 是16位, 一个字由两个字节组成 , 字节=byte ,一个字节8位, 位=bit 如果没有特殊说明kb 就是指 k*bit
    物理地址为20位 如10000H 用段地址*16+偏移地址表示
    深入学习Java线程池
    在线考试系统镜像构建、推送、部署
    容器 变成镜像提交到阿里云镜像仓库
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/3859761.html
Copyright © 2011-2022 走看看