C语言内存重点知识的讲解与习题练习
扫描二维码
随时随地手机看文章
1 程序设计的本质
所谓程序就是由语句来操作存放在计算机内存中的数据。
程序设计就是对内存直接或间接地使用。可见了解内存分配乃是编程者的第一要务。
2变量的属性
对变量起作用的属性有两个:数据类型和存储类型
不同的存储类型提供了变量的作用域,链接及存储时期的不同组合
所谓作用域就是一个标识符能够起作用的范围
①函数原型作用域 函数
②代码块作用域 局部变量和函数参数
③文件作用域 全局变量
3一个C变了具有下列链接之一
外部链接——一个标识符能够在其他编译单元中或在定义它的编译单元中的其他范围被调用 全局变量
内部链接——一个标识符能在定义它的编译单元中的其他范围内被调用,但是不能在其他编译单元中被调用 静态全局变量
空链接——仅能够在声明它的范围内被调用
4一个C变量具有一下存储时期之一
静态存储时期(static)和自动存储时期(auto)
static变量分配在静态存储区,在程序运行期间不释放
static局部变量程序结束时释放,但是它的作用域也仅仅是在函数或者块的内部可见尽管如此我们可以使用指针在它不可见的位置来访问它
static局部变量在编译时进行初始化,且仅作一次初始化
如果不赋初值,在编译时会自动赋值为0。
注意:对于具有文件作用域的变量,关键字static表明链接类型,并非
存储时期,表示变量具有内部链接
例:#include
#include
存储类 时期 作用域 链接 声明方式
自动 自动 代码块 空 代码块内
寄存器自动 代码块 空 代码块内,使用register 具有外部
链接的静态 静态 文件 外部 所有函数之外 具有内部
链接的静态 静态 文件 内部 所有函数之外,使用static
空链接静态 静态 代码块 空 代码块内,使用static
5 内存划分:
栈区 存放局部数据
•由系统按栈原则管理
•编译时就已经“规划”好了,运行时才使用
•短命,函数执行完则释放。
•用户无法干预变量的诞生和消亡
静态区 存放static修饰的数据和全局数据
•编译时已确定并初始化了
•不按栈原则管理,但仍受“作用域”的制约
堆区 存放程序动态申请的数据 malloc calloc
•长命
•无名
•用户可以干预变量的诞生和消亡
•在程序运行时才动态分配
•申请可能失败
代码区 存放程序的代码 常量 不可以被修改
•存有程序的所有执行代码
•每段代码都有名称—函数名
•用户无法干预,只能通过函数名调用
C语言的动态内存分配核心函数有: malloc( )、calloc( )申请堆内存
free( )释放堆内存
注意:千万不要对非NULL指针所指向的堆空间重复释放。不可++ 或-- 释放,释放时候指针==NULL 两者不可缺一
6
分配机制/分配责任 释放机制/释放责任
静态内存 这种内存在编译时就规划好了,在程序运行期 间一直存在。是由编译 器负责分配的。 程序退出时释放,不用程序员参与。
栈内存 函数调用临时创建的。为函数返回、函数形 参、函数中定义的局部 变量在栈里申请空间。函数退出时释放,不用程序员参与。
堆内存 程序员根据需要用malloc等函数创建的内存。 在适当时机由程序员用free释放。
习题 1打印文字练习。随机产生要录入的文字,用户输入录入个数,计算用户录入文字耗时。
#include
{
int num_char;
void _random(int number);
int count_char(char * str_one,char* str_two);
printf("请输入要生成的字母个数n");
scanf("%d",&num_char);
int t1=time(NULL);
_random(num_char);
printf("%sn",str1);
scanf("%s",str2);
int right=count_char(str1,str2);
float percentage=(float)right/num_char;
int t2=time(NULL);
int _time=(int)difftime(t2,t1);
printf("输入正确了%d个字母,正确率为%f%.n",count_char(str1,str2),100*percentage);
printf("共用了%d秒n",_time);
}
void _random(int number)
{
int i = 0;
srand((unsigned)time(NULL));
for(i;i<number;i++)
{
str1[i]=(char)(rand()%26+97);
}
}
int count_char(char * str_one,char* str_two)
{
int count=0;
while(1)
{
if((*str_one==*str_two)&&(*str_one!=' ')&&(*str_two!=' '))
{
count++;
}else if((*str_one == ' ')||(*str_two == ' '))
{
return count;
break;
}
str_one++;
str_two++;
}
return count;
}
2
实现一个“可变长二维数组”,这个二维数组的行数可由输入决定,每行的元素个数仍可由输入决定。每个数组元素值都是1.
执行结果如下:
请输入行数:
5
请输入第1行的元素个数:
20
请输入第2行的元素个数:
34
请输入第3行的元素个数:
17
请输入第4行的元素个数:
9
请输入第5行的元素个数:
25
11111111111111111111
1111111111111111111111111111111111
11111111111111111
111111111
1111111111111111111111111
#include"stdio.h"
#include"stdlib.h"
void main()
{
int rows;
int **row;
int *q,*p;
int i,j;
printf("请输入行数:n");
scanf("%d",&rows);
row=(int **)malloc(sizeof(int)*rows);
if( NULL == row)
{
printf("Insufficient memory available!n" );
return;
}
p=(int *)malloc(sizeof(int)*rows);
if( NULL == p)
{
printf("Insufficient memory available!n" );
free(row);
row=NULL;
return;
}
for(i=0;i<rows;i++)
{
printf("请输入第%d行的元素个数:n",i+1);
scanf("%d",&p[i]);
row[i]=(int *)malloc(sizeof(int)*p[i]);
if( NULL ==row[i])
{
printf("Insufficient memory available!n" );
free(p);
p=NULL;
return;
}
q=row[i];
for(j=0;j<p[i];j++)
q[j]=1;
}
for(i=0;i<rows;i++)
{
q=row[i];
for(j=0;j<p[i];j++)
{
printf("%d",q[j]);
}
printf("n");
}
free(p);
p=NULL;
for(i=0;i<rows;i++)
{
free(row[i]);
row[i]=NULL;
}
free(row);
row=NULL;
}