使用指针与共同体测试机器的大小端
共同体与大小端的概念
共同体:
(1)共用体union和结构体struct在类型定义、变量定义、使用方法上很相似。
(2)共用体和结构体的不同:结构体类似于一个包裹,结构体中的成员彼此是独立存在的,分布在内存的不同单元中,他们只是被打包成一个整体叫做结构体而已;共用体中的各个成员其实是一体的,彼此不独立,他们使用同一个内存单元。可以理解为:有时候是这个元素,有时候是那个元素。更准确的说法是同一个内存空间有多种解释方式。
(3)共用体union就是对同一块内存中存储的二进制的不同的理解方式。
(4)在有些书中把union翻译成联合(联合体),这个名字不好。现在翻译成共用体比较合适。
(5)union的sizeof测到的大小实际是union中各个元素里面占用内存最大的那个元素的大小。因为可以存的下这个就一定能够存的下其他的元素。
(6)union中的元素不存在内存对齐的问题,因为union中实际只有1个内存空间,都是从同一个地址开始的(开始地址就是整个union占有的内存空间的首地址),所以不涉及内存对齐。
注意:
(1)相同点就是操作语法几乎相同。
(2)不同点是本质上的不同。struct是多个独立元素(内存空间)打包在一起;union是一个元素(内存空间)的多种不同解析方式。
大小端字节序:
字节序是指多字节数据在计算机内存或计算机网络传输时各字节的存储顺序。
端字节序(Little endian):低字节序放在低地址,低位存放再内存的其实地址。
大端字节序(Big endian): 高位存放再内存的起始地址。
网络字节序=大端字节序,其中X86CPU使用的时小端字节序,所以在进行网络数据传输的过程要进行字节序的转换,如果字节序不一致,会导致数据在传输过程中损坏。
C语言测试机器的大小端
下面是使用共同体和指针的方法测试机器的大小端
#include <stdio.h>
#include <stdlib.h>
typedef union{
int a;
char b ;
}u1;
//共同体测试方法
void union_big_little(void)
{
u1 s1;
s1.a=1;
if (s1.b==1)
{
printf("小端字节序\n");
}
else
{
printf("大端字节序\n");
}
}
//指针测试方法
void pointer_big_little(void)
{
int a=1;
if (*((char*)&a)==1)
{
printf("小端字节序\n");
}
else
{
printf("大端字节序\n");
}
}
int main(void)
{
union_big_little();
return 0;
}
内存分布与测试原理
如下是程序函数变量在栈内存的分布
测试原理:
先说使用指针的测试方法,其实共同体的本质也是指针的测试方法。
pointer_big_little()函数定义了一个int a=1,又整形数占用四个字节但是初始化值为1,转换成16进制就是0x01只用占用一个字节就能存储,所以如果机器是小端字节序的话这个数据0x01就会存储在低地址,高地址存储的就是0;如果是大端字节序地位的0x01数据就会存储在高地址,低地址的值就是0,此时我们对a变量取地址得到a变量的指针并将其强制转换为char型的指针(强制转换的本质就是转换对内存数据的解析方式)并对这个char类型的指针进行解引用,因为char类型只占用一个字节所以int型变量低地址的一个字节的内存数据被当成char类型来解引用,取去来低地址的字符0或1就可以判断a变量的低字节0x01被存储在高位地址还是低位地址了,从而判断机器的大小端。
使用共同体的原理和使用指针的原理完全相同,指针的方法是共同体方法的本质,共同体所有变量使用的是同一块内存,使用不同类型的变量就是使用不同的方法对同一块内存数据进行解引用。