1、结构体对齐规则:
1、结构体变量的首地址,必须是结构体变量中“最大基本数据类型成员所占字节数”的整数倍。
2、结构体变量中每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍。
3、结构体变量的总大小,为结构体变量中“最大基本数据类型所占字节数”的整数倍。
2、使用宏定义,进行结构体成员相对偏移量的计算。
#define sum(type,exp) (int)&(((struct type*)0)->exp)
/*将0强转为结构体类型指针,此时零就是首地址,然后引用要计算偏移量的变量,然后将此地址转换为int型就会得出该变量的偏移量。*/
//举例
struct student
{
int age;
char name[10];
char id[10];
};
int main()
{
//计算id的偏移量
printf("%d\n", sum(student,id));//14
return 0;
}
3、为什么进行字节对齐
1、内存大小的基本单位是字节,理论上来讲,可以从任意地址访问变量,但实际上,cpu并非逐字节读写内存,而是以2,4或者8的倍数来读写内存,因此就会对基本数据类型的地址做出一系列限制,即它必须是2、4或者8的倍数,那么就需要各种数据类型按照一定规则在空间上排列,这就是对齐。
2、有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个周期就可以读出32bit,如果存放在奇地址开始,就需要读两个周期,并且还要对两个周期的字节进行拼接,因此效率会下降很多。
3、同样结构在不同平台的对齐方式可能不一样,因此大小可能也不同,在无意识的情况下,互相发送数据可能会出现错乱,甚至引发严重问题。
4、结构体和联合体的区别
联合体(union)与结构体(struct)有一 些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间。而在联合体中,各成员共享同一段内存空间, 一个联合变量的长度等于各成员中最长的长度。
应该说明的是,这里所谓的共享不是指把多个成员同时装入一个联合变量内,而是指该联合变量可被赋予任一成员值但每次只能赋一种值,赋入新值则冲去旧值。
5、将端数据转换为大段。(int)
思路:定义一个联合体,将整形数据存放在联合体里,然后通过改变联合体内的char数组来对其进行改变。将原先的属组顺序颠倒即可。如下图,将0,3交换,将1,2交换。
#include<stdio.h>
union x
{
int a;
char ar[4];
};
void Swap(char* x, char* y)//交换函数
{
char temp = *x;
*x = *y;
*y = temp;
return;
}
int main()
{
union x f = {};
scanf_s("%x", &f.a);
Swap(&f.ar[0], &f.ar[3]);
Swap(&f.ar[1], &f.ar[2]);
//将ar[0],ar[3]相互交换,ar[1]和ar[2]相互交换
printf("%x", f.a);
}
6、堆和栈的区别
栈区和堆区的区别:
1)申请方式: 栈区内存由系统自动分配,函数结束时释放;堆区内存由程序员自己申请,并指明大小,用户忘释放时,会造成内存泄露,不过进程结束时会由系统回收。
2)申请后系统的响应: 只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常提示栈溢出;堆区,空闲链表,分配与回收机制,会产生碎片问题(外部碎片)–>(固定分区存在内部碎片(分配大于实际),可变分区存在外部碎片(太碎无法分配))。
3)申请大小的限制:栈是1或者2M,可以自己改,但是最大不超过8M;堆,看主机是多少位的,如果是32位,就是4G
4)申请效率:栈由系统自动分配,速度较快,程序员无法控制;堆是由new分配的内存,一般速度较慢,而且容易导致内存碎片,但是用起来方便!
5)存储内容:栈,函数调用(返回值,各个参数,局部变量(静态变量不入栈));堆,一般在堆的头部用一个字节存放堆的大小,堆中的具体内容由程序员安排。
6)存取效率的比较:栈比堆快,Eg :char c[] = /“1234567890/”;char *p =/“1234567890/”;读取c[1]和p[1],c[1]读取时直接吧字符串中的元素读到寄存器cl中,而p[1]先把指针值读到edx中,再根据edx读取字符,多一次操作。
7)管理方式不同:栈,数据结构中的栈;堆,链表
8)生长方向:栈,高到低;堆,低到高
7、杨辉三角
int main()
{
int a[5][5] = { 0 };
int i = 0, j = 0;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j <= i; j++)
{
if (j == 0 || i == j)
{
a[i][j] = 1;
}
else
{
a[i][j] = a[i - 1][j] + a[i - 1][j - 1];
}
}
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j <=i; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}