C程序的内存开辟

目录

前言:

C/C++ 程序内存分配的区域:

1.栈区(stack)

2.堆区(heap)

3.数据段(data segment)

4.代码段(code segment)

一、printf / fprintf / sprintf

0x00 printf 函数

0x01 fprintf 函数

0x02 sprintf 函数

二、scanf / fscanf / sscanf

0x00 scanf 函数

0x01 fscanf 函数

0x02 sscanf 函数

三、总结


 

前言:

本篇博客旨在加深动态内存开辟的理解,以 C/C++ 程序的内存开辟为主题进行简要的分析。

四随后会带着讲解 scanf、fscanf、sscanf / printf、fprintf、sprintf 这些函数长得都挺像的,它们分别都是干什么的呢?本篇博客将对这些格式化输入输出函数进行一个讲解。本篇为文件操作章节延伸,新手建议学过文件操作后观看。

C/C++ 程序内存分配的区域:

1.栈区(stack)

执行函数时,函数内部局部变量的存储单元都可以在栈上创建。函数执行结束后这些存储单元会被自动释放。栈内存分配运算内置于处理器的指令集中,拥有很高的效率,但是分配的内存容量是有限的。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。

2.堆区(heap)

一般由程序员自主分配释放,若程序员不主动不释放,程序结束时可能由操作系统回收。其分配方式类似于链表。

3.数据段(data segment)

静态存储区,存放全局变量和静态数据,程序结束后由系统释放。

4.代码段(code segment)

存放函数体(类成员函数和全局函数)的二进制代码。

内存区域划分图:

实际上,普通的局部变量是在栈区分配空间的,在栈区上创建的变量,出了作用域就会销毁。但是,如果一个变量被 static 修饰,就会存放到数据段(静态区),而在数据段上创建的变量,直到程序结束才会销毁,所以生命周期因此而变长。

栈区的特点:在上面创建的变量出了作用域就销毁。

数据段的特点:在上面创建的变量直到程序结束才销毁

一、printf / fprintf / sprintf

0x00 printf 函数

 头文件:#include <stdio.h>

针对标准输出的格式化输出语句 - stdout

代码演示:printf 的用法

#include <stdio.h>

int main(void) {
    printf("Hello,World!\n");
    int a = 100;
    printf("a=%d", a);

    return 0;
}

 运行结果如下:

0x01 fprintf 函数

头文件:#include <stdio.h>

针对所有输出流的格式化输出语句 - stdout / 文件

代码演示:随便创建一个文件,在文件中写入一段话

#include <stdio.h>

char data[] = "Hey, nice to meet you~";

int main(void) {

    FILE* pf = fopen("test1.txt", "w");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }
    // 使用fprintf写文件
    fprintf(pf, "%s", data);

    fclose(pf);
    pf = NULL;

    return 0;
}

 (代码成功运行)

0x02 sprintf 函数

头文件:#include <stdio.h>

作用:把一个格式化的数据转换成字符串。

代码演示:sprintf 的用法

#include <stdio.h>

struct S {
	char arr[10];
	int age;
	float f;
};

int main(void) {
	struct S s = { "hello", 20, 3.14f };
	char buffer[100] = { 0 }; // 用于存放

	sprintf(buffer, "%s %d %f", s.arr, s.age, s.f); // 把这些信息放到buffer中了
	printf("%s\n", buffer); // 将buffer打印出来

	return 0;
}

 运行结果如下:

二、scanf / fscanf / sscanf

0x00 scanf 函数

头文件:#include <stdio.h>

针对标准输入的格式化的输入语句 - stdin

代码演示:scanf 的用法

#include <stdio.h>

int main(void) {
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    printf("a=%d, b=%d\n", a, b);

    return 0;
}

 输入10 20,运行结果如下:

0x01 fscanf 函数

头文件:#include <stdio.h>

针对所有输入流的格式化输入语句 - stdin / 文件

代码演示:fscanf 的用法

#include <stdio.h>

int data; // 存放读到的数据

int main(void) {
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 使用fscanf读文件
    fscanf(pf, "%d", &data);

    // 将读到的数据打印
    printf("%d\n", data);

    fclose(pf);
    pf = NULL;

    return 0;
}

 运行结果如下:

0x02 sscanf 函数

头文件:#include <stdio.h>

作用:从一个字符串中读取一个格式化的数据。

代码演示:利用 sscanf 从 buffer 字符串中还原出结构体的数据

#include <stdio.h>

struct S {
	char arr[10];
	int age;
	float f;
};

int main(void) {
	struct S s = { "hello", 20, 3.14f };
	struct S tmp = { 0 };

	char buffer[100] = { 0 };
	sprintf(buffer, "%s %d %f", s.arr, s.age, s.f); // 把这些信息放到buffer中了
	printf("%s\n", buffer);

	// 从buffer字符串中还原出一个结构体数据
	sscanf(buffer, "%s %d %f", tmp.arr, &(tmp.age), &(tmp.f));
	printf("%s %d %f\n", tmp.arr, tmp.age, tmp.f);

	return 0;
}

 运行结果如下:

三、总结

scanf 针对标准输入的格式化的输入语句 - stdin

fscanf 针对所有输出流的格式化的输出语句 - stdin / 文件

sscanf 从一个字符串中读取一个格式化的数据

printf 针对标准输出的格式化输出语句 - stdout

fprintf 针对所有输出流的格式化输出语句 - stdout / 文件

sprintf 把一个格式化的数据转换成字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雾里有果橙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值