第二部分—C语言提高篇_2. 内存分区

本文深入探讨C语言中的数据类型,包括数据类型概念、typedef、void数据类型以及sizeof操作符。接着讲解变量的定义和本质,然后详细阐述程序的内存分区模型,包括栈、堆、全局/静态区和常量区,解析函数调用模型和内存存放方向。
摘要由CSDN通过智能技术生成

2.1 数据类型

2.1.1 数据类型概念

什么是数据类型?为什么需要数据类型?

数据类型是为了更好进行内存的管理,让编译器能确定分配多少内存。

我们现实生活中,狗是狗,鸟是鸟等等,每一种事物都有自己的类型,那么程序中使用数据类型也是来源于生活。

当我们给狗分配内存的时候,也就相当于给狗建造狗窝,给鸟分配内存的时候,也就是给鸟建造一个鸟窝,我们可以给他们各自建造一个别墅,但是会造成内存的浪费,不能很好的利用内存空间。

我们在想,如果给鸟分配内存,只需要鸟窝大小的空间就够了,如果给狗分配内存,那么也只需要狗窝大小的内存,而不是给鸟和狗都分配一座别墅,造成内存的浪费。

当我们定义一个变量,a = 10,编译器如何分配内存?计算机只是一个机器,它怎么知道用多少内存可以放得下10?

所以说,数据类型非常重要,它可以告诉编译器分配多少内存可以放得下我们的数据。

数据类型基本概念:

  • 类型是对数据的抽象;
  • 类型相同的数据具有相同的表示形式、存储格式以及相关操作;
  • 程序中所有的数据都必定属于某种数据类型;
  • 数据类型可以理解为创建变量的模具: 固定大小内存的别名;

2.1.2 typedef的功能

  1. 起别名 -  简化struct关键字
  2. 区分数据类型
  3. 提高代码移植性

示例代码:

typedef unsigned int u32;    //起别名、提高代码移植性
typedef struct _PERSON       //简化struct关键字
{
	char name[64];
	int age;
}Person;

void test(){
	u32 val;                 //相当于 unsigned int val;
	Person person;           //相当于 struct PERSON person;
}

2.1.3 void数据类型

void字面意思是”无类型”,void* 无类型指针,无类型指针可以指向任何类型的数据。

void定义变量是没有任何意义的,当你定义void a,编译器会报错。

void真正用在以下三个方面:

   1.限定函数返回值,函数参数

   2.void * 万能指针  可以不通过强制类型转换就转成其他类型指针

   3.常用于数据类型的封装

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

2.1.4 sizeof操作符

sizeof是c语言中的一个操作符,类似于++、--等等。sizeof能够告诉我们编译器为某一特定数据或者某一个类型的数据在内存中分配空间时分配的大小,大小以字节为单位。

基本语法:

sizeof(变量);

sizeof 变量;

sizeof(类型);

sizeof 注意点:

  • sizeof返回的占用空间大小是为这个变量开辟的大小,而不只是它用到的空间。所以对结构体用的时候,大多情况下就得考虑字节对齐的问题了;
  • sizeof返回的数据结果类型是unsigned int;
  • 要注意数组名和指针变量的区别。通常情况下,我们总觉得数组名和指针变量差不多,但是在用sizeof的时候差别很大,对数组名用sizeof返回的是整个数组的大小,而对指针变量进行操作的时候返回的则是指针变量本身所占得空间。而且当数组名作为函数参数时,在函数内部,形参也就是个指针,所以不再返回数组的大小

示例代码:

//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");    //整型遇到无符号整型,整型会自动转换成无符号整型,输出结果 
                                  //所以为“结果大于0”
	}

	int b = 5;
	if (sizeof(b) - 10 < 0)
    {
		printf("结果小于0\n");
	}
	else
    {
		printf("结果大于0\n");                      //输出结果为“结果大于0”
	}
}

//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("array size: %d\n", sizeof(pArr));

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

2.1.5 数据类型总结

  1. 数据类型本质是固定内存大小的别名,是个模具,C语言规定:通过数据类型定义变量;
  2. 数据类型大小计算(sizeof);
  3. 可以给已存在的数据类型起别名typedef;
  4. 数据类型的封装(void 万能类型);

2.2 变量

2.1.1 变量的概念

既能读又能写的内存对象,称为变量;

若一旦初始化后不能修改的对象则称为常量。

变量定义形式: 类型  标识符, 标识符, … , 标识符

2.1.2 变量名的本质

  • 变量名的本质:一段连续内存空间的别名;
  • 程序通过变量来申请和命名内存空间 int a = 0;
  • 通过变量名访问内存空间;
  • 不是向变量读写数据,而是向变量所代表的内存空间中读写数据;
  • 变量的修改方式
    1. 直接修改
    2. 间接修改
    void test()
{
	int a = 10;
	//1. 直接修改
	a = 20;
	printf("直接修改,a:%d\n",a);
	//2. 间接修改
	int* p = &a;
	*p = 30;
	printf("间接修改,a:%d\n", a);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值