不得不懂的C语言重点——内存管理

存储类

基本术语

作用域
  • 作用域:☞指程序中可以访问一个标识符的一个或多个区域。
  • 一个C变量的作用域可以是代码块作用域、函数原型作用域、文件作用域。

1.代码块作用域

  • 在代码块中定义的变量具有代码块作用域。
  • 从该变量被定义的地方到包含该定义的代码块的末尾该变量均可见。
    如下:变量cleo和patrick都有直到结束花括号的代码块作用域
double blocky(double cleo)//形式参量具有代码块作用域
{
  double patrick=0.0;
  ...
}
  • 在一个内部代码块中声明的变量,其作用域只局限于该代码块。

2.函数原型作用域

  • 适用于函数原型中使用的变量名。
  • 函数原型作用域从变量定义处一直到函数声明的末尾。

3.文件作用域

  • 一个在所有函数之外定义的变量具有文件作用域。
  • 作用域:从变量定义处到包含该定义的文件结尾处都是可见的。
    如:
#include<stdio.h>
int units=o;//具有文件作用域的变量(全局变量)
int main(void)
{
...
return 0;
}
链接
  • 一个C变量具有:外部链接/内部链接/空链接;

    1.具有代码块作用域或者函数原型作用域的变量具有:空链接(表示这些变量是由其定义所在的代码块或者函数原型所私有的);
    2.具有文件作用域的变量:可能有内部或者外部链接;(一个具有外部链接的变量可以在一个多文件程序的任何地方使用;一个具有内部链接的变量可以在文件的任何地方使用;);
    如下:

int g=5;//无static,外部链接
static int d=3;//有,内部链接
int main()
{
}
存储时期
  • 一个C变量:静态存储时期/自动存储时期;

    1.静态存储时期:具有文件作用域的变量具有静态存储时期。(如果一个变量具有静态存储时期,它在程序执行期间将一直存在。)
    2.自动存储时期:具有代码块作用域的变量一般情况下具有自动存储时期。(在程序进入定义这些变量的代码块时,将为这些变量分配内存;当退出这个代码块时,分配的内存将被释放。)

存储类(5种)

  • C使用作用域、链接、存储时期来定义5种存储类:自动、寄存器、具有代码块作用域的静态、具有外部链接的静态、具有内部链接的静态。
    在这里插入图片描述
自动变量
  • 属于自动存储类的变量具有自动存储时期、代码块作用域、空链接。

  • 默认情况下,在代码块或函数的头部定义的任意变量都属于自动存储类。

  • 可以使用关键字auto来使您的意图更清晰。
    如:int main(void) { auto int p; ...}

  • 注意:如果在内层代码块定义了一个具有和外层代码块变量同一名字的变量:那么在内层代码块定义的名字是内层代码块所使用的变量。即内层定义覆盖了外部定义,但当运行离开内层代码块时,外部变量重新恢复作用。

寄存器变量
  • 因为寄存器变量多是存放在一个寄存器而非内存中,所以无法获得寄存器变量的地址。

  • 很多方面,寄存器变量和自动变量是一样的。

  • 通过使用关键字register可以声明寄存器变量。
    如:int main(void) {register int q; ...}

  • 声明一个寄存器变量仅是一个请求,而非一条直接的命令。编译器必须在您的请求与可用寄存器的个数或可用高速内存的数量之间做权衡。

具有代码块作用域的静态变量
  • 创建具有代码块作用域兼具静态存储时期的局部变量。(包含这些变量的函数完成工作时,他们并不消失。)
  • 使用存储类说明符static(这提供了静态存储时期)在代码块内声明(这提供了代码块作用域和空链接)创建。
  • 对函数参量不能使用static。~~int work(static int flu);~~
具有外部链接的静态变量
  • 具有外部链接的静态变量具有文件作用域、外部链接、静态存储时期。
  • 把变量的定义声明放在所有函数之外,即创建了一个外部变量。
  • 若变量是在别的文件中定义的,使用extern来声明该变量是必须的。
extern char cloo;
int main(void)
{
}
int a=1;//定义声明
int main(void)
{
extern int a;//引用声明
}
具有内部链接的静态变量
  • 这种存储类的变量具有静态存储时期、文件作用域、内部链接。
  • 使用存储类说明符static在所有函数外部进行定义。
static int a=1;
int main (void)
{

存储类说明符

auto、register、static、extern、typedef(与内存存储无关)

存储类和函数

  • 函数也具有存储类。
  • 函数可以是外部的(默认情况下)或者静态的。
double gamma();//默认外部
static double beta();//内部
extern double deta();//外部

分配内存:malloc()和free()

  • 使用库函数来分配和管理内存。
函数malloc()/calloc()
  • malloc(a):参数a为所需内存字节数。
  • 返回开辟的内存的第一个字节的地址。(所以把这个地址赋值给一个指针变量,并使用该指针来访问那块内存。)
    如:
double * p;
p=(double *)malloc(30 *sizeof(double));//30个double的空间,把p指向该空间所需位置。

可以使用p[0]来访问内存块的第一个元素,p[2]来访问第二个元素,依次类推。所以可以用作数组。

  • 函数calloc(a,b):参数a是所需内存单元的数量。b是每个单元以字节计的大小。特性:将块中的全部位都置为0;
    如:
long * m;
m=(long *)calloc(100,sizeof(long));
//建立了100个long长度的单元
函数free()
  • 一般,对应每个malloc()调用,应该调用一次free()。它释放先前分配的地址。
  • free()的参数是先前malloc()返回的地址。
  • 所分配内存的持续时间从调用malloc()分配内存开始,到调用free()释放内存结束。
  • 在头文件stdlib.h。
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>

int main(void)
{
	double * p;
	int max;
	int number;
	int i = 0;

	puts("什么是最大的啥");
	scanf("%d",&max);
	p = (double*)malloc(max * sizeof(double));//用作数组
	if (p == NULL)
	{
		puts("记忆位置失败");
		exit(EXIT_FAILURE);

	}
	puts("Enter the values(q to quit);");
	while (i < max && scanf("%1f", &p[i]) == 1)
		++i;
	printf("这里有你的%d条", number = i);
	for (i = 0; i < number;i++)
	{
		printf("%7.2f", p[i]);
		if (i % 7 != 0)
			putchar('\n');

	}
	puts("Done");
	free(p);
	return 0;
}
动态分配内存和变长数组
  • 不同:变长数组(VAL)是自动存储的,即自动释放内存。
    如:
int n=5;
int m=6;
int ar2[n][m];//变长数组
int (*p2)[6];
int (*p3)[m];
p2=(int(*)[6])malloc(n*6*sizeof(int));//n*6数组
p3=(int(*)[m])malloc(n*m*sizeof(int));//n*m数组

ANSI C的类型限定词

类型限定词const
类型限定词volatile
  • volatile告诉编译器该变量除了可被程序改变以外还可被其他代理改变。
volatile int locl;//locl是一个易变的位置
volatile int * ploc;//ploc是一个易变的位置
类型限定词restrict
  • restrict通过允许编译器优化某几种代码增强了计算支持。它只可用于指针,并表明指针是访问一个数据对象的唯一且初始的方式。
int ar[10];
int * restrict a=(int *)malloc(10*sizeof(int));
int * par=ar;

指针a是访问malloc()分配的内存的唯一且初始的方式。

参考文献
  • 《C Primer Plus》 Stephen Prata著
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值