这两个表达有什么不同吗?

14

由于我的编译器对这两段代码给出了不同的统计数据,我想知道它们之间有什么区别,如果有的话?

第一段代码:

typedef const struct process_data
{
   uint8_t *name;
   void (*p_func)(void);
} process_data_t;

process_data_t processes = {15,16};

第二个是:

typedef struct process_data
{
   uint8_t *name;
   void (*p_func)(void);
} process_data_t;

const process_data_t processes = {15,16};

请注意,const限定符已从类型定义移动到结构的定义中。对我来说,这两个节选没有区别,但编译器/链接器统计数据显示使用第二段代码时消耗了更少的闪存空间(该平台是具有受限资源的微控制器)。


1
看一下 map 文件中的差异。然后回报 :) - Eugene Sh.
请提供一个更完整的示例,足以展示问题。 - old_timer
3个回答

5

编译器在解析这些声明时可以有一定的自由度,但通常情况下,它们之间的区别如下:

  • typedef 的含义是:这是一个始终为 const 的类型,意味着无法在任何变量中取消对此类型的const限制。当您传递这种数据或指向它的指针时,它们将是 const 的。当然,强制转换“有效”,但仅适用于另一种类型,并可能导致未定义行为。

  • const 数据的含义是:该数据是 const 的,但此类型的其他数据可能不是,因此,在变量和指向此类型的指针之间进行一定程度的“取消 const 限制”是可以接受的。当然,如果有人将指向此数据的指针转换为非 const,并且它确实位于只读存储器中,则会出现问题。

因此,它们的最终结果相同,但存在微妙的差异。编译器如何解释这些声明完全取决于编译器本身。实际上,typedef 很少使用(在我看来是这样),因此编译器可能针对更常见的情况进行了优化。


是的,我发现这是一个编译器特定的问题。它将常量解释为放置在闪存(ROM)中的内存。真正的问题在于,在这个编译器中,const似乎是一个特定的“每个变量”声明。它不会通过类型传播。所以我有点浪费了你们的时间,对此我很抱歉。无论如何,谢谢大家。 - Hairi

4

在数据定义中使用const和通常的const有所不同,如果你从带有限定符的对象中移除const,则可能会导致未定义行为(至少在C ++中)。

除了语言方面的问题,其原理很明显:我们希望将它们作为只读镜像的一部分, 同时仍然允许那些知道自己在做什么的人使用const_cast,因为这也有好的理由

在C语言中, 我们基本上具有相同的动机:将常量放入只读内存中,但是允许转换工作。当限定符附加到类型时,这并不能强烈保证用户打算将变量放入只读内存中,因此编译器可能会在这里采取谨慎的态度。


0

常量被存储在只读内存中 - 我猜你只是在移动数据的位置。没有更多信息很难说100%。


3
const 限定的对象不一定被存储在只读内存中。考虑 const int r = rand(); - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接