C语言内存分区

一、数据类型

1.数据类型概念

C语言内存分区_数组
C语言内存分区_数组_02

2.数据类型别名

C语言内存分区_数组_03

3.void数据类型

C语言内存分区_数组_04

//1. void修饰函数参数和函数返回
void test01(void){
	printf("hello world");
}

//2. 不能定义void类型变量
void test02(){
	void val; //报错
}

//3. void* 可以指向任何类型的数据,被称为万能指针
void test03(){
	int a = 10;
	void* p = NULL;
	p = &a;
	printf("a:%d\n",*(int*)p);
	
	char c = 'a';
	p = &c;
	printf("c:%c\n",*(char*)p);
}

//4. void* 常用于数据类型的封装
void test04(){
	//void * memcpy(void * _Dst, const void * _Src, size_t _Size);
}

4.sizeof操作符

C语言内存分区_数组_05
C语言内存分区_i++_06

//1. sizeof基本用法
void test01(){
	int a = 10;
	printf("len:%d\n", sizeof(a));
	printf("len:%d\n", sizeof(int));
	printf("len:%d\n", sizeof a);
}

//2. sizeof 结果类型
void test02(){
	unsigned int a = 10;
	if (a - 11 < 0){
		printf("结果小于0\n");
	}
	else{
		printf("结果大于0\n");
	}
	int b = 5;
	if (sizeof(b) - 10 < 0){
		printf("结果小于0\n");
	}
	else{
		printf("结果大于0\n");
	}
}

//3. sizeof 碰到数组
void TestArray(int arr[]){
	printf("TestArray arr size:%d\n",sizeof(arr));
}
void test03(){
	int arr[] = { 10, 20, 30, 40, 50 };
	printf("array size: %d\n",sizeof(arr));

	//数组名在某些情况下等价于指针
	int* pArr = arr;
	printf("arr[2]:%d\n",pArr[2]);
	printf("array size: %d\n", sizeof(pArr));

	//数组做函数函数参数,将退化为指针,在函数内部不再返回数组大小
	TestArray(arr);
}

5.数据类型总结

C语言内存分区_函数调用_07

二、变量

1.变量的概念

C语言内存分区_i++_08

2.变量名的本质

C语言内存分区_i++_09

三、程序的内存分区模型

1.内存分区

运行之前

C语言内存分区_函数调用_10
C语言内存分区_函数调用_11
C语言内存分区_函数调用_12
C语言内存分区_数据类型_13

运行之后

C语言内存分区_函数调用_14
C语言内存分区_数据类型_15
C语言内存分区_i++_16

2.分区模型

栈区

C语言内存分区_i++_17

堆区

C语言内存分区_函数调用_18
C语言内存分区_i++_19
C语言内存分区_数据类型_20

void test01(){
	
	int* p1 = calloc(10,sizeof(int));
	if (p1 == NULL){
		return;
	}
	for (int i = 0; i < 10; i ++){
		p1[i] = i + 1;
	}
	for (int i = 0; i < 10; i++){
		printf("%d ",p1[i]);
	}
	printf("\n");
	free(p1);
}

void test02(){
	int* p1 = calloc(10, sizeof(int));
	if (p1 == NULL){
		return;
	}
	for (int i = 0; i < 10; i++){
		p1[i] = i + 1;
	}

	int* p2 = realloc(p1, 15 * sizeof(int));
	if (p2 == NULL){
		return;
	}

	printf("%d\n", p1);
	printf("%d\n", p2);

	//打印
	for (int i = 0; i < 15; i++){
		printf("%d ", p2[i]);
	}
	printf("\n");

	//重新赋值
	for (int i = 0; i < 15; i++){
		p2[i] = i + 1;
	}
	
	//再次打印
	for (int i = 0; i < 15; i++){
		printf("%d ", p2[i]);
	}
	printf("\n");

	free(p2);
}

全局/静态区

C语言内存分区_函数调用_21
C语言内存分区_i++_22
C语言内存分区_c语言_23
C语言内存分区_c语言_24

总结

C语言内存分区_数据类型_25

3.函数调用模型

函数调用流程

C语言内存分区_数组_26
C语言内存分区_数据类型_27
C语言内存分区_i++_28

调用惯例

C语言内存分区_数据类型_29
C语言内存分区_i++_30
C语言内存分区_c语言_31

函数变量传递分析

C语言内存分区_数据类型_32
C语言内存分区_数据类型_33
C语言内存分区_数组_34

栈的生长方向和内存存放方向

C语言内存分区_函数调用_35

//1. 栈的生长方向
void test01(){

	int a = 10;
	int b = 20;
	int c = 30;
	int d = 40;

	printf("a = %d\n", &a);
	printf("b = %d\n", &b);
	printf("c = %d\n", &c);
	printf("d = %d\n", &d);

	//a的地址大于b的地址,故而生长方向向下
}

//2. 内存生长方向(小端模式)
void test02(){
	
	//高位字节 -> 地位字节
	int num = 0xaabbccdd;
	unsigned char* p = &num;

	//从首地址开始的第一个字节
	printf("%x\n",*p);
	printf("%x\n", *(p + 1));
	printf("%x\n", *(p + 2));
	printf("%x\n", *(p + 3));
}