您的位置:首页 > 其它

[TwistedFate]程序存储区划分、动态申请内存、内存操作函数

2015-10-21 20:13 323 查看

内存区划分

内存区划分为5个区:栈区 堆区(程序员管理) 静态区 常量区 代码区

内存地址: 内存地址大 ———-> 内存地址小

代码区

电脑的存储都是以二进制数据存储的
书写的代码 会被系统转化为二进制数据 存储在代码区


常量区

常量区存储常量的特点:
常量是程序运行期间 不能改变量


char *str =":";
// 把h更改成w
// *(str + 1) = 'w'; // 运行崩溃
// 指针的赋值是指针的重指向(没有改变常量的值)
str = "haha";


char str[] = "zhuang";
// 数组名字 地址 数组首元素的地址
// 数组首元素的常量地址
// 把h 更改成 w
// 是把常量区的常量字符串拷贝到栈区
str[1] = 'w';
// str = "haha" 错误 不能更改


静态区

静态区存储两种变量
(1)静态变量:
利用关键字 static 修饰的变量 叫做静态变量 并且存储在静态区
`static int number1;`
特点:1.如果初始化不赋值,默认是0;
2.只初始化一次
举例比较:


void function()
{
static int num = 10;
num++
printf("%d ",num);
}
// 输出三次结果为:11 12 13
void function1()
int num1 = 10;
num1++;
printf("%d ",num1);
// 输出结果三次为:11 11 11


(2)全局变量


静态区变量 保存周期:直到你的程序运行结束,静态变量才会被释放

栈区

栈区大概7M - 8M

出栈与入栈的规则:先入栈——>栈底, 再出栈

入栈:又称压栈

之所以栈区 容量不是特别大又不会出现崩溃的现象 是因为 栈区频繁的进行出栈入栈 只要一次性不把栈空间堆满 不会轻易的出现崩溃

注意:定义变量的时候 切记给初值 避免出现莫名其妙的问题

堆区

堆区 是程序员开辟空间 是程序员释放空间

手动开辟空间 手动释放空间

堆区的空间 大概就是全部存储空间

开辟空间函数

void *malloc(字节大小)
void * 表示无类型指针 开辟了四个字节的堆内存空间


// 给整型指针p指向的位置 开辟了四个字节的堆内存空间
int *p = malloc(4);
*p = 10;
printf("%d \n",*p);

char *str = malloc(8);
strcpy(str, "wang");    // 正确
stpcpy(str, "wangwangwang");  //错误的,开辟了多少空间 不要超过开辟的空间
printf("%s\n",str);
int *p1 = malloc(4);
*p1 = 5;
short *p2 = malloc(4);  // 开辟多少空间 最好用多少
*p2 = 10;
*(p2 + 1) = 15;


释放空间函数

free(void *)
1.标记删除 不会抹去该空间存储的数据 只会把这块空间标记为可用
2.把指针置空


// 开辟空间
int *p = malloc(4);
// 使用空间
*p = 10;
printf("%d\n",*p);
// 释放空间
free(p);
p = NULL;


// 改错


int *p = malloc(sizeof(int) * 5);
for(int i = 0;i < 5;i++)
{
*p = i + 1;
p++;
}
free(p);
// 指针发生了变化 释放了本不属于你的开辟区域 就会崩溃
// 修改 把指针改回去
free(p - 5);
p = NULL;


/** 练习

* 有⼀字符串,其中包含数字,提取其中的数字.要求动态分配内存保存

提⽰: 先计算出有⼏个数字,然后根据数字的个数来开辟空间

*/

char str[] = "dsad123dsa23";
int count = 0;
for(int i = 0;i < strlen(str);i++)
{
if(str[i] >= '0' && str[i] <= '9' )
{
count++;
}
}
// 开辟空间
char *strValue = malloc(count + 1); //加1是因为字符串有个'\0'
// 记录数字该放的位置
int index = 0;
for(int i = 0; i < strlen(str);i++)
{
if(str[i] >= '0' && str[i] <= '9')
{
strValue[idnex] = str[i];
index++;
}
}
// 加上'\0'
strValue[index] = '\0';
printf("%s",strValue);
// 释放空间
free(strValue);
strValue = NULL;


/** 练习2:

* 输⼊3个学员的姓名,动态分配内存保存学员姓名,并在最后输出

*/

char *word[3] = {0};
char str[] = {0};
for(int i = 0;i < 3;i++)
{
printf("请输入一个字符:\n");
scanf("%s",str);
// 开辟空间
words[i] = malloc(strlen(str) + 1);
// 保存字符串
strcpy(words[i], str);
}
for (int i = 0; i < 3; i++) {
printf("%s\n",words[i]);
// 释放空间
free(words[i]);
words[i] = NULL;
}


其他分配函数

在堆内存中 开辟 n * size 个空间 并且把开辟的空间清零 因为有一个清零的过程 所以效率偏低

// calloc(int n, size)

int *p = calloc(3, sizeof(int));
free(p);
p = NULL;


重新分配函数 realloc

realloc(原分配地址,新空间大小)

两种情况:

情况1:如果原来分配的地址 可以扩充空间 那么就在原来的地址扩充

情况2:如果原来分配的地址 不能扩充了 那么系统会重新分配一个空间 并且把原来的地址存储的数据拷贝到新空间 然后系统自动释放原地址的空间

int *p_old = malloc(10);
int *p_new = realloc(p_old, 25);
printf("%p %p\n",p_old,p_new);
// free(p_old);     // 过度释放
free(p_new);
p_new = NULL;


内存操作函数

// 把开辟的空间 多少字节 重置成 c

// memset(开辟的空间的指针, int c, 字节)

// 用途:把开辟好的空间 清零

int *p = malloc(sizeof(int) * 4);
for (int i = 0; i < 4; i++) {
p[i] = i + 5;
}
// 清零
memset(p, 0, 16);
for (int i = 0; i < 4; i++) {
printf("%d ",p[i]);
}


// 从来源拷贝到目的地 多少个字节

// memcpy(目的地,来源 , 字节数)

char str1[] = “wanglong”;

char str2[] = “44”;

memcpy(str1, “W”,1);

memcpy(str1 + 3, str2, 2);

printf(“%s”,str1);

// 比较函数
// 两个地址 按字节 进行比较返回第一个不同的差值
// memcmp(指针1, 指针2, 字节数)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: