编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

C语言栈区、堆区的使用,typedef和sizeof的使用

gowuye 2024-04-25 04:43 12 浏览 0 评论

1、栈区的使用

栈区写入内存的的顺序是先进后出。

存放的是函数的参数、返回值、局部变量

由编译器管理数据开辟和释放

变量的生命周期在该函数结束后自动释放

不要返回局部变量的值,因为局部变量在函数执行之后就释放掉了,无法读取原来的内存

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



//栈区注意事项,不要返回局部变量的地址
int* func()
{
	int a = 10;
	return &a;
}

static void test01()
{
	int* p = func();

	//结果不重要了,在func函数结束后a的内存已经被释放掉了,我们无权限操作这块内存
	printf("a=%d\n", *p);//只有第一次输出结果正确,下面的值不确定
	printf("a=%d\n", *p);
}


char* getstring()
{
	char str[] = "hello world";
	return str;
}
static void test02()
{
	char* p = NULL;
	p=getstring();
	printf("%s\n", p);//结果是乱码
}
int main0501()
{
	//test01();
	test02();
	return 0;
}

2、堆区的使用

堆区的空间远远大于栈区

它没有先进后出的数据结构

由程序员手动开辟和释放,malloc、calloc开辟free释放

注意:

如果主调函数中没有给指针分配内存,那么被调函数中需要利用高级指针给主调函数中的指针分配内存

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

int g_b = 100;

int* getspcae()
{
	int* p = malloc(sizeof(int) * 5);

	if (p = NULL)
	{
		return NULL;
	}

	for (int i = 0; i < 5; i++)
	{
		p[i] = i + 100;
	}
	return p;
}

static void test01()
{
	int* p = getspcae();

	for (int i = 0; i < 5; i++)
	{
		printf("%d\n", p[i]);
	}
	free(p);
	p = NULL;//防止p是野指针
}



//如果主调函数中没有给指针分配内存,被调函数使用统计指针是修饰不到主调函数中的指针
static void allocatespace(char* pp)//被调函数
{
	char* temp = malloc(100);
	if (temp == NULL)
	{
		return;
	}
	memset(temp, 0, 100);//将内存置空
	strcpy(temp, "hello world");
	pp = temp;
}

static void test02()//主调函数
{
	char* p = NULL;
	allocatespace(p);
	printf("%s\n", p);//打印结果是null
}





static allocatespace2(char**pp)
{
	char* temp = malloc(100);
	memset(temp, 0, 100);
	strcpy(temp, "hello world");
	*pp = temp;
}
static void test03()
{
	char* p = NULL;
	allocatespace2(&p);
	printf("%s\n", p);
}


int main0601()
{
	//test01();
	//test02();
	test03();
	return 0;
}

3.数据区放的是静态变量、全局变量以及常量

static静态变量: 编译阶段分配内存,只能在当前文件内使用,只初始化一次

ertern全局变量:C语言下默认的全局变量前都默认隐藏了该关键字

4.const修饰的变量

直接修改const修饰的全局变量:失败

简介修改const修饰的全局变量:失败,原因是放在常量区,受到保护

直接修改const修饰的局部变量:失败

直接修改const修饰的局部变量:成功,该局部变量其实放到了栈区,是伪常量

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


//1.静态变量
static int a = 10;//值初始化一次,在编译阶段就分配内存了,属于内部链接属性,只能在当前文件使用

static void test01()
{
	static int b = 20;//局部静态变量,作用域只能在test01中

	//a和b的生命周期是一样的
}


//2.全局变量
int g_a = 100;//在c语言下,全局变量前都隐藏了关键字extern ,属于外部连接属性

static void test02()
{
	extern int g_b;//g_b是外部链接属性,下面再使用这个变量时不用报错
	printf("g_b=%d\n", g_b);
}
int main0701()
{
	test02();
	


	return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//1、const修饰的全局变量,即使语法通过,但运行时也无法修改成功。
const int a = 10;//放在常量区

static void test01()
{
	//a = 100;//err
	int* p = &a;
	*p = 100;

	printf("%d\n", a);
}


//2、const修饰的局部变量
static void test02()
{
	const int b = 10;//分配到栈区
	//b = 100;//err



	//间接修改成功
	int* p = &b;
	*p = 100;
	printf("%d\n", b);//可修改b的值

	//int a[b];//err   b是伪常量
}




//字符串常量
static void test03()
{
	char* p1 = "hello world";
	char* p2 = "hello world";
	char* p3 = "hello world";



	printf("%d\n", p1);
	printf("%d\n", p2);
	printf("%d\n", p3);
	printf("%d\n", &"hello world");

	p1[0] = 'z';//不允许修改字符串常量
	printf("%c\n", p1[0]);
}
int main()
{
	//test01();
	//test02();
	test03();
	return 0;
}

5.字符串常量

不同编译器的处理方式有所区别

ANSI并未指定它的修改方式

有些编译器可以修改字符串常量,但有些不可以,某些编译器将相同的字符串常量看做同一个字符串常量

6.void的使用方式

无类型,不可以创建变量,无法分配内存

限定函数返回值

限定函数参数列表

void*是万能指针,不需要强制转化就可以给其他指针赋值

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


//1、无类型不可以创建变量
static void test01()
{
	//void a = 10;//err 系统不知道给a分配多少内存

}

//2、限定函数返回值
static void func()
{
	//return 10;
}

static void test02()
{
	//func();
	//printf("%d\n", func());
}

//3、限定函数参数列表
static int func02()
{
	return 10;
}
static void test03()
{
	//printf("%d\n", func02(10));
}

//4、void * 万能指针
static void test04()
{
	void* p = NULL;
	int* pInt = NULL;
	char* pChar = NULL;

	//pChar =(char*) pInt;
	pChar = p;//p是万能指针 不需要强制类型转换
	printf("size of void * = %d\n", sizeof(p));//不论什么指针都是4字节
}
int main0201()
{
	/*test02();
	test03();*/


	system("pause");
	return 0;

}

7.sizeof的使用

sizeof的本质其实是一个运算符,类似于+-*/

当统计某类型占的空间时需要加()

当统计mou变量占的空间时无需加()

返回值的类型是无符号整形,即unsigned int

数组名称如果作为函数参数,会退化为指针,指向数组首元素

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

//1、sizeof 的本质是一个操作符 类似于+-*/
static void test01()
{
	//对于数据类型,sizeof必须用()使用,对于变量不用加()
	printf("size of in = %d\n", sizeof(int));

	double d = 3.14;

	printf("size of d =%d\n", sizeof d);
}

//2、sizeof的返回值是unsigned int 无符号整型
static void test02()
{
	//unsigned int a = 10;
	//if (a - 20 > 0)//当unsigned int 和int类型数据做运算,编译器会将数据全部转化为unsigned int型
	//{
	//	printf("大于0\n");
	//}
	//else
	//{
	//	printf("小于0\n");
	//}

	if (sizeof(int) - 5 > 0)
	{
		printf("大于0%u\n", sizeof(int) - 5);
	}
	else
	{
		printf("小于0\n");
	}
}


//3、sizeof可统计数组的长度
//当数组名作为函数参数是,会退化为指针,指针指向数组中首元素
static void calculateArray(int arr[])
{
	printf("arr数组大小:%d\n", sizeof(arr));

}
static void test03()
{
	int arr[] = { 1,2,3,4,5,6,7,8 };
	//printf("arr数组大小:%d\n", sizeof(arr));
	calculateArray(arr);
}

int main0301()
{
	//test01();
	//test02();
	test03();
	return 0;
}

8.typedef的使用

它可以给类型起别名

简化struct关键字

区分数据类型

提高代码的可移植性

//#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>//std标准 i input 输出  o  output输出
#include<string.h>//字符串相关函数 strcpy strcmp
#include<stdlib.h>// malloc free等


//1、typedef的使用:简化结构体关键字  struct
//struct person
//{
//	char name[64];
//	int age;
//};
//typedef struct person mperson;

//主要功能就是给类型起别名
//语法 typedef 原名 别名
typedef struct person
{
	char name[64];
	int age;
}mperson;


static void test1()
{
	struct person p1 = { "张三",15 };
	mperson p2 = { "李四",12 };

}


//2、区分数据类型
static void test02()
{
	//char* p1, p2;  //只有p1是char*  p2是char型


	typedef char* PCHAR;
	PCHAR p1, p2;//p1 p1都是char*

	char* p3, * p4;//p3 和 p4都是char*
}

//3、提高代码可移植性
typedef int MYINT;//typedef long long  MYINT;只替换long long 即可
static void test03()
{
	MYINT a1 = 10;
	MYINT a2 = 10;
}
int main0101()
{
	



	system("pause");//按任意键暂停,阻塞功能
	printf("hello world\n");
	return EXIT_SUCCESS;//返回  正常退出即0
}

相关推荐

R语言数据挖掘实践——支持向量机的常用函数
R语言数据挖掘实践——支持向量机的常用函数

e1071包是R语言中用于支持向量机建模与分析的软件包,其主要用于支持向量机的模型构建,提供核心函数svm()来建立支持向量机的基础模型,并且可辅助使用pred...

2024-05-18 12:15 gowuye

R数据分析:如何做聚类分析,实操解析
R数据分析:如何做聚类分析,实操解析

Clusteringisabroadsetoftechniquesforfindingsubgroupsofobservationswi...

2024-05-18 12:14 gowuye

用R语言做数据分析——马赛克图
用R语言做数据分析——马赛克图

到目前为止,我们已经学习了许多可视化定量或连续型变量间关系的方法。但如果变量是类别型的呢?若只观察单个类别型变量,可以使用柱状图或者饼图;若存在两个类别型变量,...

2024-05-18 12:14 gowuye

用R语言做数据分析——方差分析基本概论
用R语言做数据分析——方差分析基本概论

在实际工作中,影响一件事的因素是很多的,我们总是希望通过各种试验来观察各种因素对试验结果的影响。例如,不同的生产厂家、不同的原材料、不同的操作规程,以及不同的技...

2024-05-18 12:14 gowuye

R语言数据分析实战:数据清洗与可视化
R语言数据分析实战:数据清洗与可视化

《R语言数据分析实战:数据清洗与可视化》是一本深入浅出的实践指南,专为对数据分析感兴趣的读者精心编撰。本书旨在帮助读者掌握R语言这一强大的统计分析工具,通过实例...

2024-05-18 12:13 gowuye

用R语言做数据分析——双因素方差分析
用R语言做数据分析——双因素方差分析

在双因素方差分析中,受试者被分配到两因子的交叉类别组中。以基础安装中的Tooth-Growth数据集为例,随机分配60只豚鼠,分别采用两种喂食方法(橙汁或维生素...

2024-05-18 12:13 gowuye

用R语言做数据分析——独立两样本和K样本检验
用R语言做数据分析——独立两样本和K样本检验

coin包简介对于独立性问题,coin包提供了一个进行置换检验的一般性框架,通过这个包,我们可以回答如下问题:响应值与组的分配独立吗?两个数值变量独立吗?两个类...

2024-05-18 12:13 gowuye

用R语言做数据分析——用回归做方差分析
用R语言做数据分析——用回归做方差分析

之前提到方差分析和回归都是广义线性模型的特例,之前文章的所有设计都可以用lm()函数来分析。为了更好地理解输出结果,需要弄明白在拟合模型时,R语言是如何处理类别...

2024-05-18 12:13 gowuye

数据分析R语言——数据结构
数据分析R语言——数据结构

数据分析R语言——数据结构数组数组(array)与矩阵类似,但是维度可以大于2.数组通过array()函数创建。形式如;myarray<-array(v...

2024-05-18 12:13 gowuye

R语言数据挖掘实践——关联分析的常用函数
R语言数据挖掘实践——关联分析的常用函数

arules和arulesViz是R语言中两个专用于关联分析的软件包。其中arules用于关联规则的数字化生成,提供Apriori和Eclat这两种快速挖掘频繁...

2024-05-18 12:12 gowuye

R语言数据挖掘实践——判别分析的常用函数
R语言数据挖掘实践——判别分析的常用函数

判别算法在R语言中实现主要涉及4个软件包中的相关函数,它们依次为MASS、klaR、class和kknn。其中MASS包含有大量实用而先进的统计计数函数及适用数...

2024-05-18 12:12 gowuye

用R语言读取Excel、PDF和JSON文件,终于有人讲明白了
用R语言读取Excel、PDF和JSON文件,终于有人讲明白了

导读:本文将讨论Excel、PDF等文件的读取,以及相应函数的参数设置。作者:刘健邬书豪如需转载请联系华章科技下图总结了主要程序包,希望读者在日常练习和工作中...

2024-05-18 12:12 gowuye

R语言数据挖掘实践——聚类分析的常用函数
R语言数据挖掘实践——聚类分析的常用函数

使用R语言可以轻松实现聚类分析,stats、cluster、fpc和mclust是常用的四个聚类分析软件包。stats主要包含一些基本的统计函数,如用于统计计算...

2024-05-18 12:12 gowuye

用R语言做数据分析——时间序列分类
用R语言做数据分析——时间序列分类

时间序列分类是根据已标注的时间序列建立一个分类模型,然后使用分类模型预测未标记时间序列的类别。从时间序列中抽取出新特征肯呢个有助于提高分类模型的性能。特征提取技...

2024-05-18 12:11 gowuye

一文看懂用R语言读取Excel、PDF和JSON文件(附代码)
一文看懂用R语言读取Excel、PDF和JSON文件(附代码)

导读:本文将讨论Excel、PDF等文件的读取,以及相应函数的参数设置。作者:刘健邬书豪如需转载请联系华章科技下图总结了主要程序包,希望读者在日常练习和工作中...

2024-05-18 12:11 gowuye

取消回复欢迎 发表评论: