‘壹’ 判断一个机器使用的是大端存储还是小端存储
下面的程序可以判断一台机器是大端存储还是小端存储。
[cpp]view plain
#include<stdio.h>
intmain(intargc,char**argv){
//联合(union)中,所有成员引用的是内存中相同位置,
//由具体成员类型决定了这些位如何被解释
union{
shorts;
charc[sizeof(short)];
}un;
un.s=0x0102;//16进制数中,02是低序字节,01是高序字节
if(sizeof(short)==2){
if(un.c[0]==1&&un.c[1]==2){
printf("big-endian ");
}elseif(un.c[0]==2&&un.c[1]==1){
printf("little-endian ");
}else{
printf("unknow ");
}
}else{
printf("sizeof(short)=%d ",sizeof(short));
}
return0;
}
‘贰’ 大端模式和小端模式的区别及如何判断的存储器的模式
一个数需要超过一个字节来存储时,就有大端和小端的区别,只用一个字节时,无所谓大小端
低位的放在低地址,也就是小个在前,叫小端,反之叫大端
c和c++需要面对这样的问题,java等高级语言已经屏蔽这个差异,不需要额外处理
在c中,可以用以下代码片段来判断是大端还是小端
union {char c; int i;} u;
u.i = 1;
if(u.c == 1){//小端}
else{//大端}
‘叁’ 刚才的Union我又遇到问题了!
你这个问题涉及到union的对齐问题以及大小端的问题
c语言规定union中的成员都是低地址对齐的,比如你存了int(16bit)和char,在内存中是这样的。
内存从高=>低
======== ======== int
======== char
然后,所谓大小端问题是说数据的高低位和内存的高低位之间的对应关系
看下面的图
内存高----------------------------低
H【XXXXXXXX】L【XXXXXXXX】
如果内存的高位表示的是数据的高位(低位对应低位),那么值是H*2^8+L,叫做小端
如果内存的高位表示的是数据的低位(低位对应高位),那么值是L*2^8+H,叫做大端
到底是大端还是小端是由操作系统决定的,大部分都是小端
‘肆’ c语言 union 所占内存大小问题
联合体(union)
当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union);
1)联合体是一个结构;
2)它的所有成员相对于基地址的偏移量都为0;
3)此结构空间要大到足够容纳最"宽"的成员;
4)其对齐方式要适合其中所有的成员;
下面举例说明:
如联合体
1 union U
2 {
3 char s[9];
4 int n;
5 double d;
6 };
s占9字节,n占4字节,d占8字节,因此其至少需9字节的空间。然而其实际大小并不是9,
用运算符sizeof测试其大小为16.这是因为这里存在字节对齐的问题,9既不能被4整除,
也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。
从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,
即其大小必须满足两个条件:
1)大小足够容纳最宽的成员;
2)大小能被其包含的所有基本数据类型的大小所整除。
‘伍’ 笔试面试7 如何判断一个系统的存储方式是大端还是小端
简单来说,从内存地址增加的方向来说,大端就是先存放高序字节,小端就是先存放低序字节。
例如:0x0102
-------->内存增加的方向------>
地址A------>地址A+1
大端:01 02
小端:02 01
判断方法是利用union的一个特性,那就是里面的变量共享一段内存。
可以定义一个union.
union Test{
short num;//2byte
char c[sizeof(num)];//2byte
} ;
然后存入一个0x0102或者其他数字到test.num中,因为共享内存的原因,可以访问c[1],c[2],查看里面的值来判断大小端。
一个实现是(参照unix网络编程中的一个例子):
[cpp] view plain print?
#include <stdio.h>
#include <conio.h>
union Test{
short num;
char c[sizeof(short)];
};
int main()
{
union Test t;//C++ 直接声明为Test t即可
t.num=0x0102;
if(t.c[0]==1&&t.c[1]==2)
printf("大端!\n");
else if(t.c[0]==2&&t.c[1]==1)
printf("小端!\n");
else
printf("未知!\n");
getch();
return 0;
}
在Win7 32bit里面用DEV c++运行的结果为:
或者更简单的是存一个short值,然后取其地址。
[cpp] view plain print?
#include <stdio.h>
#include <conio.h>
int main()
{
short int num=0x0201;
char *p=#
if(*p==0x02)
printf("大端!\n");
else if(*p==0x01)
printf("小端!\n");
else
printf("未知!\n");
getch();
return 0;
}
测试结果:
‘陆’ c语言,union有什么用
本质上来说和结构体是一样的,但是从包装的角度来看有差异。
1、union中可以定义多个成员,union的大小由最大的成员的大小决定。
2、union成员共享同一块大小的内存,一次只能使用其中的一个成员。
3、对某一个成员赋值,会覆盖其他成员的值(也不奇怪,因为他们共享一块内存。但前提是成员所占字节数相同,当成员所占字节数不同时只会覆盖相应字节上的值,比如对char成员赋值就不会把整个int成员覆盖掉,因为char只占一个字节,而int占四个字节)
4、联合体union的存放顺序是所有成员都从低地址开始存放的。
下面看一个简单的代码:
#include<stdio.h>
typedefunion{
charc;
inta;
intb;
}Demo;
intmain(intargc,char**argv)
{
Demod;
d.c='H';
d.a=10;
d.b=12;
printf("size:%d ",sizeof(d));
printf("%c %d %d ",d.c,d.a,d.b);
return0;
}
具体用法举例:
1. 为了方便看懂代码。
比如说想写一个3 * 3的矩阵,可以这样写:
structMatrix
{
union
{
struct
{
float_f11,_f12,_f13,_f21,_f22,_f23,_f31,_f32,_f33;
};
floatf[3][3];
}_matrix;
};
structMatrixm;
这两个东西共同使用相同的空间,所以没有空间浪费,在需要整体用矩阵的时候可以用
m._matrix.f (比如说传参,或者是整体赋值等);需要用其中的几个元素的时候可以用m._matrix._f11那样可以避免用m.f[0][0](这样不大直观,而且容易出错)。
2. 用在强制类型转换上(比强制类型转换更加容易看懂)
下面举几个例子:
(1). 判断系统用的是big endian 还是 little endian(其定义大家可以到网上查相关资料,此略)
#defineTRUE1
#defineFALSE0
#defineBOOLint
BOOLisBigEndian()
{
inti=1;/*i=0x00000001*/
charc=*(char*)&i;/*注意不能写成charc=(char)i;*/
return(int)c !=i;
}
如果是little endian字节序的话,那个i = 1;的内存从小到大依次放的是:0x01 0x00 0x00 0x00,如是,按照i的起始地址变成按照char *方式(1字节)存取,即得c = 0x01;
反之亦然
也许看起来不是很清晰,下面来看一下这个:
BOOLisBigEndian()
{
union
{
inti;
charc;
}test;
test.c=2;
returntest.i!=2;
}
这里用的是union来控制这个共享布局,有个知识点就是union里面的成员c和i都是从低地址开始对齐的。同样可以得到如此结果,而且不用转换,清晰一些。
什么,不觉得清晰??那再看下面的例子:
(2). 将little endian下的long long类型的值换成 big endian类型的值。已经知道系统提供了下面的api:long htonl(long lg);作用是把所有的字节序换成大端字节序。因此得出下面做法:
longlonghtonLL(longlonglg)
{
union
{
struct
{
longlow;
longhigh;
}val_1;
longlongval_2;
}val_arg,val_ret;
if(isBigEndian())
returnlg;
val_arg.val_2=lg;
val_ret.val_1.low=htonl(val_arg.val_1.high);
val_ret.val_1.high=htonl(val_arg.val_1.low);
returnval_ret.val_2;
}
只要把内存结构的草图画出来就比较容易明白了。
(3).为了理解c++类的布局,再看下面一个例子。有如下类:
classTest
{
public:
floatgetFVal(){returnf;}
private:
inti;
charc;
floatf;
};
Test t;
不能在类Test中增加代码,给对象中的f赋值7.0f.
classTest_Cpy
{
public:
floatgetVal(){returnf;}
floatsetVal(floatf){this->f=f;}
private:
inti;
charc;
floatf;
};
....
intmain()
{
Testt;
union
{
Testt1,
Test_Cpyt2;
}test;
test.t2.setVal(7.0f);
t= test.t1;
assert(t.getVal()==7.0f);
return0;
}
说明:因为在增加类的成员函数时候,那个类的对象的布局基本不变。因此可以写一个与Test类一样结构的类Test_Cpy,而多了一个成员函数setVal,再用uinon结构对齐,就可以给私有变量赋值了。(这种方法在有虚机类和虚函数机制时可能失灵,故不可移植)至于详细的讨论,网上有,这个例子在实际中没有用途,只是用来考察这个内存布局的使用而已.
union在操作系统底层的代码中用的比较多,因为它在内存共赏布局上方便且直观。所以网络编程,协议分析,内核代码上有一些用到union都比较好懂,简化了设计。
‘柒’ C语言中使用union是怎么判断处理器大小端的
union Charge
{
char arr[2];
short num;
};
int main()
{
union Charge charge;
charge.arr[0] = 1;
charge.arr[1] = 2;
if (charge.num == 0x0201)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
‘捌’ C语言:例子解释,关于union
可能的值是266(小尾) 或 17432576 (32 位大尾序) 或 2561(16位大尾)
参考下面的代码
#include<stdio.h>
union{
inti;
charx[2];
}a;
intmain(void)
{char*p;
inti=0;
a.x[0]=10;
a.x[1]=1;
printf("%d ",a.i);
printf("联合a共占%d个字节 ",sizeof(a));
p=(char*)(&a);
for(i=0;i<sizeof(a);++i)
{
printf("0x%08X--------",p+i);
printf("%02X ",*(p+i));
}
return0;
}
‘玖’ C语言 共用体union的问题
首先理解共同体是同一个内存段可以用来存放集中不同类型的成员,但在每一瞬间只能存放其中一个成员,而不是同时存放一个值。你的程序是将123456789L长整型放进去复制给c.a,因此按整数存储在变量单元中,如果按照“%d”输出c.a则会输出123456789,如果按照“%f”格式输出c.b,系统会将存储单元中的信息按浮点数形式来处理,其数值部分则为0,所以输出为0.000000
‘拾’ 写一段c语言代码,来验证处理器的存储方式是大端存储还是小端存储
#include<stdio.h>
intmain(void)
{
int=0x12345678;
char*p=&;
inti=0;
for(i=0;i<4;i++)
printf("%X ",*p++);
return0;
}