变量和内存

全局和局部变量

1、局部变量作用域:从创建到所在函数结束
在这里插入图片描述
2、如果在函数中 函数创建顺序从右往左
在这里插入图片描述
打印变量地址结果:从高向低增长
在这里插入图片描述
注意:不同函数中变量名可以一样,其所对应的地址不一样;

3、全局变量:作用在整个项目中,使用的前提是需要在使用的文件中进行声明
在这里插入图片描述
4、声明变量就是可以使用这个变量,声明不会分配内存空间
在这里插入图片描述
注意:如果在函数外部是全局变量 在函数外面是局部变量
如果全局变量写在主函数下面,想使用需要声明
在这里插入图片描述

静态全局和局部变量

1、静态局部变量和局部变量 可以被赋值
在这里插入图片描述
2、静态局部变量和局部变量区别: 只能被初始化一次,可以被多次赋值
在这里插入图片描述
全局静态变量只能作用于当前文件中,不能在全部文件中使用
在这里插入图片描述
3、auto区分局部变量和全局变量
在这里插入图片描述

注意:定义的时候自带声明,但只能在使用它的函数之上

4、声明为严谨起见,都写在头文件 .h 中
在这里插入图片描述
静态函数作用域当前文件
在这里插入图片描述
5、一个括号之内就是未命名的函数体;
在这里插入图片描述

for循环中的i 从循环开始到循环结束 与 循环外面的 int i =100; 不冲突;

小结:
在这里插入图片描述
声明周期
在这里插入图片描述

内存布局

1、程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、初始化数据区(data)和未初始化数据区(bss)
在这里插入图片描述
2、数据区:
在这里插入图片描述

注意:LINUX系统编程会将数据区拆开

内存四区模型
在这里插入图片描述
注意:
栈区:
①只有c语言将数组放在栈区;
②如果在程序中创建的的数据应该放在堆区;栈去大小:在不同的操作系统中系统分配给每一个程序的战区空间大小不同,一般Windows是1-8M不等,一般LINUX是1-16M不等;
③死循环搞不死电脑 ,不会沾满内存但会沾满CUP;
④递归会导致程序崩溃,栈溢出;
⑤不是公用,可以被访问;
堆区:
开辟堆空间大小与内存有关;

内中位置模型:
在这里插入图片描述
注意:栈区向下生长,大小端对齐

3、malloc在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域
格式:malloc(分配大小)
在这里插入图片描述
释放堆空间
在这里插入图片描述

注意:创建完的堆空间,在使用完之后不释放,会占用内存空间

4、误区:
开辟0个空间即是野指针
在这里插入图片描述
为野指针赋值操作
在这里插入图片描述
未释放空间,释放会报错
在这里插入图片描述
报错结果:
在这里插入图片描述
注意:多次释放空间会报错
5、释放空间流程
先判断在释放 释放完成 变成空指针
在这里插入图片描述
6、置为空,在释放程序不会报错
在这里插入图片描述
7、例子:堆空间开辟数组和冒泡排序:

①空间开辟
在这里插入图片描述

②随机数
在这里插入图片描述
③循环赋值
在这里插入图片描述

④冒泡排序
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <time.h>

#define MAX 10

int main13()
{
	srand((unsigned int)time(NULL));
	int * p = (int *)malloc(sizeof(int) * MAX);
	//int len = sizeof(p) 
	for (int i = 0; i < MAX; i++)
	{
		//*(p + i) = rand() % 50;
		p[i] = rand() % 50;
		//*p++ = rand() % 50;
	}
	for (int i = 0; i < MAX; i++)
	{
		printf("排序前:\n");
		printf("%d\n", p[i]);
	}
	for (int i = 0; i < MAX - 1; i++)
	{
		for (int j = 0; j < MAX - i - 1; j++)
		{
			if (p[j] > p[j + 1])
			{
				int temp = p[j];
				p[j] = p[j + 1];
				p[j + 1] = temp;
			}
		}
	}
	printf("排序前:\n");

	for (int i = 0; i < MAX; i++)
	{
		printf("%d\n", p[i]);
	}
	free(p);


	system("pause");
	return EXIT_SUCCESS;
}

8、strcopy 拷贝
strcopy操作对空间,会将拷贝的字符串全都放到堆空间中,这样就会导致超出堆空间 使程序出现错误;
在这里插入图片描述
注意:开辟多大堆空间,就要操做多大堆空间
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main1401()
{

	//开辟多大堆空间 就要操作多大堆空间
	char * p = malloc(sizeof(char) * 10);//\0

	strcpy(p, "hello world");

	printf("%s", p);


	free(p);


	system("pause");
	return EXIT_SUCCESS;
}

int main14()
{
	char arr[100] = "hello world";
	arr[1] = 'A';
	char * p = malloc(sizeof(char) * 100);

	char * p1 = "hello world";
	char * p2 = "hello world";
	printf("%p\n", p1);
	printf("%p\n", p2);
	strcpy(p, "hello world");
	*p = 'A';
	printf("%p\n", p);
	printf("%s\n", p);

	free(p);
	return 0;
}

9、重置 memset 参数:目标 值 字节大小
在这里插入图片描述
注意:①memset可以重置内存区域的值 初始化值为0 但在char类型中可以初始化
相同的值
②memset 重置内存的值,前提是重置区域可读可写

重置数组(栈区内容)
在这里插入图片描述

10、memcpy拷贝:拷贝src所指的内存内容的前n个字节到dest所值的内存地址上
①可以从栈区拷贝到堆区 也可以从堆区拷贝到栈区
在这里插入图片描述
注意:源地址与目标地址不能发生重叠
在这里插入图片描述
strcpy 与mencpy的不同
①函数参数不同
②strcpy拷贝字符串 memcpy 可以拷贝一块内存
③strcpy与memcpy拷贝结束标志不同
在这里插入图片描述
11、memmove()功能用法和memcpy()一样,
区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。
在这里插入图片描述

注意:
拷贝重叠内存地址不会出现问题,但是效率比较低
如果拷贝源与拷贝目标没有重叠两个函数效率一样

12、memcmp:比较s1和s2所指向内存区域的前n个字节
在这里插入图片描述
类型不同,但在内存中存的ASCII码相同,所以比较的内容相同
在这里插入图片描述注意:不限类型比对

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main1501()
{
	//int * p = (int *)malloc(sizeof(int) * 10);
	参数:目标 值 字节大小
	//memset(p, 0, 40);
	//for (int i = 0; i < 10; i++)
	//{
	//	printf("%d\n", p[i]);
	//}
	//char * p = malloc(sizeof(char) * 10);
	//memset(p, 0, 10);
	//printf("%s\n", p);


	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memset(arr, 0, 40);
	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}

	//free(p);
	//system("pause");
	return EXIT_SUCCESS;
}
int main1502()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//int *p = malloc(sizeof(int) * 10);
	//memcpy(p, arr, 40);
	//for (int i = 0; i < 10; i++)
	//{
	//	printf("%d\n", p[i]);
	//}

	//free(p);

	memcpy(&arr[2], arr, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}
	char arr1[] = { 'h','e','l','l','o' };
	char * p = malloc(100);
	memset(p, 0, 100);
	//1、函数参数不同
	//2、strcpy拷贝字符串 memcpy 可以拷贝一块内存
	//3、拷贝结束标志不同 strcpy \0 memcpy  以个数为结尾
	strcpy(p, arr1);
	memcpy(p, arr1, 5);
	printf("%s\n", p);
	free(p);
	return 0;
}

int main1503()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//memmove拷贝重叠内存地址不会出现问题  但是效率比较低   如果拷贝源和拷贝目标没有重叠  两个函数效率一样
	memmove(&arr[2], arr, 20);

	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}
}
int main()
{
	//int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//int arr2[5] = { 1,2,3,4 };

	//int val = memcmp(arr1, arr2, 20);
	//if (!memcmp(arr1, arr2, 8))
	//{
	//	printf("前两个数组元素内容相同");
	//}
	//printf("%d\n", val);

	//int * p1 = malloc(sizeof(int) * 10);
	//char * p2 = malloc(sizeof(char) * 40);

	//memcpy(p1, "hello", 6);
	//memcpy(p2, "hello", 6);
	//if (!memcmp(p1, p2, 6))
	//{
	//	printf("内容相同\n");
	//}
	//else
	//{
	//	printf("内容不相同\n");

	//}

	int a = 0xffff;
	char b = 0xffff;
	//printf("%d\n", b);
	if (!memcmp(&a, &b, 2))
	{
		printf("内容相同\n");
	}
	else
	{
		printf("内容不相同\n");

	}

	//free(p1);
	//free(p2);
	//练习   求出三名学生 三门功课成绩 并排序   通过堆空间来实现  arr[3][3];
	int ** p = (int **)malloc(sizeof(int *) * 3);
	p[0] = (int *)malloc(sizeof(int) * 3);
	p[1] = (int *)malloc(sizeof(int) * 3);
	p[2] = (int *)malloc(sizeof(int) * 3);

	p[0][0] = 90;
	p[0][1] = 80;
	p[0][2] = 70;

	//排序

	free(p[0]);
	free(p[1]);
	free(p[2]);

	free(p);


	return 0;
}

13、栈内存存储过程
栈遵从规则:后进先出 先进后出
在这里插入图片描述
练习题:1、求出三名学生三门功课成绩 并排序 通过堆空间实现
思路:二维数组模型arr[3][3]
①开辟一个指针的堆空间
在这里插入图片描述

②存三门成绩
在这里插入图片描述

③为三门成绩赋值
在这里插入图片描述

④释放:先释放内层 在释放外层
在这里插入图片描述

释放例图演示:
在这里插入图片描述
2、冒泡排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值