大小端问题
在我们发送数据的时候,我们首先要确定的是大端还是小端模式来进行的,在接收方接收的数据必须知道数据是大端还是小端模式,这个才能正确地读取和存储数据,否则就会出现问题。
一个三十二位的二进制程序中存储有两种方式,
1:高字节对高地址(大端模式)
2:高字节对应低地址(小端模式)
区分大小端的方法
1:利用地址强制类型转换
void test()
{
int i = 1;
char j = *((char*)&i);
if(j == 1)
{
printf("小端\n");
}
}
2:利用联合体性质:不同类型变量共享同一块内存
void test2()
{
union un
{
int i;
char c;
}u;
u.i = 1;
if(u.c ==1)
{
printf("小端");
}
}
因为他们是公用同一块内存的,所以定义i = 1;
那么,我们就可以查看c是多少,因为c是char型的,所以只能看八个比特位,所以当查到u.c == 1时,我们就可以知道它是小端存储。
const与volatile介绍
我们知道const修饰变量后,变量是只读的;
但是到底是为什么呢?
编译器在编译期间,可能对代码进行了优化,
当编译器看到这里的num被const修饰,从语义上讲这里的num是不希望被改变的。那优化的时候就可以吧num的值存放到寄存器(以提高访问效率)。以后只要使用num的地方都去寄存器中取,那即使num对应的内存中的值发生变化,寄存器也是感知不到的。
volatile关键字对num修饰
这个时候num可以被改变
划重点了
编译时不优化,执行时不缓存,每次需从内存中读出(保证内存的可见性)
static小结
static修饰局部变量
改变该变量的“记忆性”,“全局性”
所谓“记忆性”:指的是在两次函数调用时,在第二次调用进入时,能保持第一次调用退出时的值。
全局性:延长变量的生命周期
注意事项:每次调用时,都指向同一块内存,具有不可重入性。
static修饰静态变量/函数
用来表示不能被其他文件访问的全局变量和函数。修饰函数使其成为静态函数,但此处“static”的含义不是指存储方式,而是指对函数作用域仅局限本文件(即内部函数),此时的static只起作用域限制作用。
防止不同人编写不同函数时,跟其他文件中的函数重名。
结构体的内存对齐
首先得掌握结构体对齐规则:
1:第一个成员在结构体变量偏移量为0的地址处。
2:其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数=编译器默认的一个对齐数与该成员大小的较小值。
vs中默认的值为8
Linux中的默认值为4
3:结构体总大小为最大对齐数的整数倍。
4:如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。
下面在Linux环境下展示
所以我们看到两个大小是不一样的
那么为什么存在内存对其
1:平台原因:
不是所有的硬件平台都能访问任意地址上的任意数据;某些平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2:性能原因:
数据结构(尤其是栈)应该尽可能的在自然边界上对齐,
原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对其的内存访问仅需要一次访问。
内存对齐是拿空间换时间的方法