栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

变量存储与Clion编辑器的学习与实践

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

变量存储与Clion编辑器的学习与实践

目录
    • 一、变量存储
      • 1.内存分区概念
      • 2.STM32上分区验证
      • 3.在Ubuntu中进行分区验证
    • 二、Clion编辑器的学习与实践
      • 1.Clion的下载与安装
      • 2.安装clion的相关配置环境
      • 3.安装OpenOCD环境
      • 3.利用clion点亮LED灯
    • 三、总结
    • 四、参考

一、变量存储 1.内存分区概念

1.c语言在内存中分区
栈区(stack)
由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆区(heap)
一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。它与数据结构中的堆不同,分配方式类似于链表。
全局区(静态区)(static)
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量、未初始化的静态变量在相邻的另一块区域。当程序结束后,变量由系统释放 。
文字常量区
存放常量字符串。当程序结束后,常量字符串由系统释放 。
程序代码区
存放函数体的二进制代码。
2.动静态分配内存

属性描述
静态分配内存在程序编译和链接时就确定好的内存
动态分配内存在程序加载、调入、执行的时候分配 / 回收的内存

3.内存分区详解

属性描述
.text也称为代码段(Code),用来存放程序执行代码,同时也可能会包含一些常量(如一些字符串常量等)。该段内存为静态分配,只读(某些架构可能允许修改)。 这块内存是共享的,当有多个相同进程(Process)存在时,共用同一个 text 段
.data也有的地方叫 GVAR (global value),用来存放程序中已经初始化的非零全局变量。静态分配。data又可分为读写(RW)区域和只读(RO)区域。RO 段保存常量所以也被称为 .constdata ;RW 段则是普通非常全局变量,静态变量就在其中
.bss存放程序中为初始化的和零值全局变量。静态分配。在程序开始时通常会被清零

堆和栈都属于动态分配内存,两者空间大小都是可变的。

属性描述
Stack:栈存放 Automatic Variables ,按内存地址由高到低方向生长,其最大值由编译时确定,速度快,但自由性差,最大空间不大
Heap:堆自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存 / 虚拟内存上限决定,速度较慢,但自由性大,可用空间大。

2.STM32上分区验证

在串口通信所建的工程上修改代码
bsp_usart.h 文件:
添加头文件

bsp_usart.c 文件:
添加一个 fputc函数

int fputc(int ch, FILE *f)
{
	USART_SendData(DEBUG_USARTx, (uint8_t)ch);
	
	while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
	
	return (ch);
}


main.c 文件,编写如下代码:

#include "stm32f10x.h"
#include "bsp_usart.h"  //添加 bsp_usart.h 头文件

int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;

void output(int a)
{
	printf("hello");
	printf("%d",a);
	printf("n");
}

int main(void)
{	
	//定义局部变量
	int a=2;
	static int inits_local_c=2, uninits_local_c;
	int init_local_d = 1;
	char *p;
	char str[10] = "lyy";
	//定义常量字符串
	char *var1 = "1234567890";
	char *var2 = "qwertyuiop";
	//动态分配
	int *p1=malloc(4);
	int *p2=malloc(4);
	USART_Config();//串口初始化
	output(a);
	//释放
	free(p1);
	free(p2);
	printf("栈区-变量地址n");
	printf("                a:%pn", &a);
	printf("                init_local_d:%pn", &init_local_d);
	printf("                p:%pn", &p);
	printf("              str:%pn", str);
	printf("n堆区-动态申请地址n");
	printf("                   %pn", p1);
	printf("                   %pn", p2);
	printf("n全局区-全局变量和静态变量n");
	printf("n.bss段n");
	printf("全局外部无初值 uninit_global_a:%pn", &uninit_global_a);
	printf("静态外部无初值 uninits_global_b:%pn", &uninits_global_b);
	printf("静态内部无初值 uninits_local_c:%pn", &uninits_local_c);
	printf("n.data段n");
	printf("全局外部有初值 init_global_a:%pn", &init_global_a);
	printf("静态外部有初值 inits_global_b:%pn", &inits_global_b);
	printf("静态内部有初值 inits_local_c:%pn", &inits_local_c);
	printf("n文字常量区n");
	printf("文字常量地址     :%pn",var1);
	printf("文字常量地址     :%pn",var2);
	printf("n代码区n");
	printf("程序区地址       :%pn",&main);
	printf("函数地址         :%pn",&output);
	return 0;
}

编译烧录到板子上,打开野火调试助手
按下reset键得到如下结果:

3.在Ubuntu中进行分区验证

1.使用命令创建一个hello.c文件

输入以下代码:

#include 
#include 
//定义全局变量
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
	printf("hello");
	printf("%d",a);
	printf("n");
}

int main( )
{   
	//定义局部变量
	int a=2;
	static int inits_local_c=2, uninits_local_c;
    int init_local_d = 1;
    output(a);
    char *p;
    char str[10] = "lyy";
    //定义常量字符串
    char *var1 = "1234567890";
    char *var2 = "qwertyuiop";
    //动态分配
    int *p1=malloc(4);
    int *p2=malloc(4);
    //释放
    free(p1);
    free(p2);
    printf("栈区-变量地址n");
    printf("                a:%pn", &a);
    printf("                init_local_d:%pn", &init_local_d);
    printf("                p:%pn", &p);
    printf("              str:%pn", str);
    printf("n堆区-动态申请地址n");
    printf("                   %pn", p1);
    printf("                   %pn", p2);
    printf("n全局区-全局变量和静态变量n");
    printf("n.bss段n");
    printf("全局外部无初值 uninit_global_a:%pn", &uninit_global_a);
    printf("静态外部无初值 uninits_global_b:%pn", &uninits_global_b);
    printf("静态内部无初值 uninits_local_c:%pn", &uninits_local_c);
    printf("n.data段n");
    printf("全局外部有初值 init_global_a:%pn", &init_global_a);
    printf("静态外部有初值 inits_global_b:%pn", &inits_global_b);
    printf("静态内部有初值 inits_local_c:%pn", &inits_local_c);
    printf("n文字常量区n");
    printf("文字常量地址     :%pn",var1);
    printf("文字常量地址     :%pn",var2);
    printf("n代码区n");
    printf("程序区地址       :%pn",&main);
    printf("函数地址         :%pn",&output);
    return 0;
}

编译执行文件

得到结果

从stm32和Ubuntu都可以看出:从高地址到低地址分区情况

二、Clion编辑器的学习与实践 1.Clion的下载与安装

下载传送门.
下载好之后进行安装 以下为安装步骤





等待安装完成。

2.安装clion的相关配置环境

安装MinGW
下载地址:https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/.

下载后解压完成。
打开clion软件,点击New Project

点击file->setting->Build,Execution, Deployment->Embedded Development选择Tookchains
跟据刚刚下载的mingw64文件的路径将文件调价环境中,最后点击ok

3.安装OpenOCD环境


下载解压出来
按照以下步骤添加路径

点击ok就好了

3.利用clion点亮LED灯

1.打开clion软件,选择新建工程(New Project)

利用其打开STM32CubeMX

改选芯片为STM32F103C8

再进行芯片的相关设置


选择引脚作为输出口(PC13)


生成工程
返回到clion

回到clion软件中找到main.c文件,在main.c文件中找到while(1)语句,在该语句中添加如下代码

while (1)
  {
    

    
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
		HAL_Delay(500);
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
		HAL_Delay(500);
  }
  

进行编译

烧录


结果展示:

三、总结

Clion 是一个多功能跨平台的 IDE,很有使用价值。在通过Clion进行STM32点亮LED灯的过程中,它一方面调用 STM32CubeMX 直接建立了 HAL 工程,另一方面使用 CMake 编译器完成了代码编译。在这个过程中遇到了很多bug,一遍遍的删除,一遍遍的下载,终于是做了出来。

四、参考

基于ubuntu和stm32(keil5)的C程序的内存分配问题.
CLion2021 的详细安装并基于 CLion 实现 stm32F103 点亮 LED.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/664955.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号