C语言进阶02-变量与内存、文件

C语言基础-变量与内存管理

  • 一、基本概念
    • 变量
      • 全局变量(外部变量)
      • 局部变量(自动变量)
      • 静态变量
  • 二、内存四区
    • 代码区(1):函数
    • 数据区
      • 静态区、全局区(2):存放全局变量、静态数据、常量。
      • 动态区
        • 栈区(3):局部变量(包括函数形参)
        • 堆区(4):手动分配、释放
          • C中malloc与free
          • C++中new与delete
  • 三、实践
    • 局部变量、栈的内存分配
  • 读取文件

一、基本概念

变量

一个有名字的,具有具体属性的一个存储单元。
可以理解为内存,变量的功能就是存储数据,程序运行时其值可以改变,。

每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。

汉字字符一般占两个字节,ASCII码可以表示的(包括字母)占一个字节


变量和常量:

1.常量的值不可以修改,任何尝试修改常量的操作都会导致编译错误。而变量可以通过赋值来改变。

2.常量定义后就不可修改,所以常量在定义时就必须初始化。变量可以定义时暂时不进行初始化。常量初始化的时候必须直接赋值…


全局变量(外部变量)

出现在代码块{}之外的变量就是全局变量。

生命周期:随主程序创建而创建,随主程序销毁而销毁。

使用方式:声明后程序各个部分都可以使用。

内存分配:程序开始运行时被加载(原则),放在全局数据段。
C中全局变量不能以其他变量(包括)赋值,只存在静态初始化,在编译是完成初始化。
C++中部分在编译时初始化,剩余在运行阶段 main执行前完成初始化。


局部变量(自动变量)

代码块{}内部定义的变量就是自动变量,也可使用auto显示定义。

生命周期:随局部函数甚至局部循环体存在而存在,退出就不存在。

使用方式:只能在局部使用

内存分配:堆栈中
随着编译器的不同而不同,可能在局部函数调用时一起入栈,可能用到谁入栈谁。


静态变量

是指内存位置在程序执行期间一直不改变的变量,用关键字static修饰。
代码块内部的静态变量只能被这个代码块内部访问,代码块外部的静态变量只能被定义这个变量的文件访问。


注意:extern修饰变量时,根据具体情况,既可以看作是定义也可以看作是声明;但extern修饰函数时只能是定义,没有二义性。



2.作用域:通常指的是变量的作用域,广义上讲,也有函数作用域及文件作用域等。我理解的作用域就是指某个事物能够存在的区域或范围,比如一滴水只有在0-100摄氏度之间才能存在,超出这个范围,广义上讲的“水”就不存在了,它就变成了冰或气体。

3.函数:不解释。

注意:C语言中函数默认都是全局的,可以使用static关键字将函数声明为静态函数(只能被定义这个函数的文件访问的函数)。




二、内存四区

计算机中的内存是分区来管理的,程序和程序之间的内存是独立的,不能互相访问。

代码区(1):函数

程序被操作系统加载到内存的时候(链接成可执行文件后),所有的可执行代码(程序代码指令、常量字符串、函数等)都加载到代码区。

这块内存在程序运行期间是不变的。代码区是平行的,里面装的就是一堆指令,在程序运行期间是不能改变的。函数也是代码的一部分,故函数都被放在代码区,包括main函数。

存放函数体(类成员函数和全局函数)的二进制代码。

存放常量字符串的或可独立看作文字常量区 。


数据区

静态区、全局区(2):存放全局变量、静态数据、常量。

程序结束后由系统释放。
  

动态区

局部指针变量开辟在栈上,指针内容开辟在堆上。

一个进程(运行的程序)可分为若干段:代码段、数据段、堆栈段等,其中函数所操作的空间(也就是局部变量的空间)就位于堆栈段,所谓函数分配内存大小,实际就是堆栈段指针的变化而已。

栈是由编译器自己开辟的zhidao用来存放局部数据(局部变量,未显式初始化则为随机值),编译的时候不存在,运行的时候猜出现。
堆是由程序员开辟,堆是动态内存,也就是说知道程序员去释放它,否则它一直存在。
堆的大小:你开辟多大的空间,它就有多大。在c中是malloc,c++中是new。


栈区(3):局部变量(包括函数形参)

存放为运行函数而分配的局部变量、函数参数、返回数据、返回地址等。也就是每个线程(函数等)都有自己专属的栈;栈的最大尺寸固定,超出则引起栈溢出;函数的调用过程其实就是开辟栈帧的过程,由编译器自动完成。

我们写程序时不需要考虑。栈区在程序运行期间是可以随时修改的。当一个自动变量超出其作用域时,自动从栈中弹出。
变量离开作用域后栈上的内存会自动释放。

程序对变量和函数(的参数、局部变量等)分配内存都是在栈区,程序运行过程中函数调用时参数传递也在栈上进行


堆区(4):手动分配、释放

一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收

堆(heap)和栈一样,也是一种在程序运行过程中可以随时修改的内存区域,但没有栈那样先进后出的顺序。更重要的是堆是一个大容器,它的容量要远远大于栈,这可以解决内存溢出困难。

一般比较复杂的数据类型都是放在堆中。但是在C语言中,堆内存空间的申请和释放需要手动通过代码来完成。


接下来看堆内存的分配和释放:

C中malloc与free

malloc函数:在堆中分配指定大小的内存,单位为字节(Byte),函数返回void *指针;
  free负责在堆中释放malloc分配的内存。malloc与free一定成对使用

C++中new与delete

三、实践

局部变量、栈的内存分配

1、内存存储方向:局部变量存储在栈中,栈底为高地址。所以先后定义的变量,地址为高、低。

int a=1;
int b=2;
printf("%d\n%d",&a,&b);

输出为

6356732
6356728

2、字节序
顾名思义字节的顺序,
再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。

小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址

3、分配内存的顺序以及函数中代码体(包括for循环和if条件代码体等)的作用域:
原则:使用时分配内存空间,
(1)内存定义不赋值时会随意生成一个值
(2)函数执行前,一起分配所有的局部变量空间,代码体中的变量等到使用是分配

如下one、two变量先分配空间,程序执行时three再被分配

int one = 3;

if(1)
{ int three;

printf("%d\n",&three);

}

int two = 4;
printf("%d\n%d\n",&two,&one);

输出

6356724
6356728
6356732

读取文件

#define FILE_PATH  "tt.txt"  /*文件路径*/

int main(void)
{
	char buff[512];

	FILE *p = fopen(FILE_PATH, "r");
	if (p == NULL) {
		return -1;
	}


	while (!feof(p))  {                /*读取文档,直到文件结束*/
		fgets(buff, sizeof(buff), p);
		printf(" %s \n", buff);
	}
	fclose(p);

	return 0;
}

你可能感兴趣的:(C语言)