C语言重点题目

本文详细介绍了数据结构中的字节对齐规则,包括结构体变量的地址对齐和成员偏移量计算,并通过示例展示了宏定义在计算偏移量中的应用。此外,解释了字节对齐对于CPU读写效率和跨平台兼容性的重要性。接着,对比了结构体与联合体的区别,强调联合体成员共享同一内存空间的特点。还探讨了堆和栈的区别,如内存分配、效率和生长方向等。最后,通过示例展示了杨辉三角的生成过程,展示了递归和数组在编程中的应用。
摘要由CSDN通过智能技术生成

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");
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值