const char和char指针如何在STM32中的内存中表示

时间:2017-02-28 11:17:14

标签: c pointers stm32

现在MCU如何指向变量指向的字符串是在数据存储器中还是在程序存储器中? 我将const char *转换为char *时(例如,在调用strlen函数时)编译器执行的操作是什么? char *char *可以const char *使用而不会造成任何性能下降吗?

3 个答案:

答案 0 :(得分:2)

STM32使用扁平的32位地址空间,因此RAM和程序存储器(闪存)位于相同的逻辑空间中。

Cortex核心当然知道哪种类型的存储器位于哪里,可能是通过被访问地址触发的硬件地址解码器。不过,这当然超出了C所关心的范围。

删除const不是运行时操作,因此不应该有性能开销。当然,丢弃const ,因为在某个地方你冒着某人真正相信const指针意味着数据不会被写入的风险,并且回到那个承诺可以让坏事发生。

答案 1 :(得分:1)

通过采用1MB闪存/ ROM内存和192KB RAM内存(128KB SDRAM + 64KB CCM)的STM32F4示例 - 内存映射如下所示:

  • Flash / ROM - 0x08000000至0x080FFFFF(1MB)
  • RAM - 0x20000000到0x2001FFFF(128KB)

还有更多区域有单独的地址空间,为了简化解释,我不会在这里介绍。这些记忆包括备份SRAM和CCM RAM,仅举两个例子。另外,每个区域可以是进一步划分的部分,例如RAM被分成bss,堆栈和堆。

现在关于字符串及其位置的问题 - 常量字符串,例如:

const char *str = "This is a string in ROM";

放在闪存中。在编译期间,编译器会放置一个引用此类字符串的临时符号。稍后在链接阶段,链接器(它知道每个存储器部分的具体值)一个接一个地放下每个部分中的所有数据(程序,常量数据等) - 一旦它知道每个这样的对象的具体值 - 将编译器放置的符号替换为随后出现在二进制文件中的具体值。因此,稍后在运行时上面的赋值完成后,您的str变量将被简单地赋予链接器推导出的常量值(例如0x08001234),该值直接指向字符串的第一个字节。

当谈到动态分配的值时 - 无论何时调用malloc或new,都会执行类似的任务。假设有足够的内存可用,您将获得RAM中所请求的内存块的地址,并且这些计算是在运行期间进行的。

关于const限定符的问题 - 一旦执行代码就没有意义。例如,在运行时期间,strlen函数将从传递的位置开始逐字节地遍历内存,并在遇到二进制0时结束。什么"键入"并不重要。正在分析字节数,因为一旦将代码转换为字节代码,此信息就会丢失。关于上下文中的const - 函数参数中出现的const限定符表示此类函数不会修改字符串的内容。如果尝试,则会引发编译错误,除非它隐式执行转换为非const类型。当然,您可以将非const变量作为函数的const参数传递。然而另一种方式 - 即将const参数传递给非const函数 - 将引发错误,因为此函数可能会修改您指向的内存的内容,您通过将其隐式指定为不可修改的内容const

总结并回答你的问题:你可以根据需要进行强制转换,这不会在运行时反映出来。它只是指示编译器在其类型检查期间以不同于原始变量处理给定变量的指令。但是,通过进行隐式转换,您应该知道此类转换可能不安全。

答案 2 :(得分:0)

有或没有const,假设你的字符串是真正只读的,它将改变它是否落在.data或.rodata或其他一些只读部分(.text等)。基本上它将在闪光灯或内存中。

这些部件的闪光如果我记得最好有一个额外的等待状态或基本上是公羊速度的一半......充其量。 (一般来说,对于mcus来说很常见,但也有例外)。如果你在较慢的时钟范围内运行,那么你的时钟提升时,ram性能与闪存的性能会提高。因此,对于解析该字符串的任何代码来说,在flash(const)vs sram中使用它会更慢。

这假设你的链接器脚本和引导程序是这样的.data实际上是在启动时复制到ram ...