【问题标题】:Same memory location assignment for two static variables两个静态变量的相同内存位置分配
【发布时间】:2019-01-03 21:47:23
【问题描述】:

我有下面的代码,我看到这两个变量被分配了相同的地址。这两个变量是完全不同的类型。无论如何我可以取消这个吗?以及在什么情况下,两个变量会分配相同的内存。

static int Sw_Type [];
static BOOL Sw_Update;

void main()
{
  int i;
  int bytes = 3;
  if (Sw_Update!= TRUE)
  {
    for(i = 0; i< bytes ;i++)
    {
      Sw_Type [i] = *Ver_Value;     
      Ver_Value++;          
    }
    Sw_Update= TRUE;
  }
}

这是我的代码的 sn-p,“Ver_Value”是分配给不同功能的结构。

所以我看到的问题是,当 Sw_Update 更新时,Sw_Type [1] 正在更新,我看到这两个具有相同的内存地址。

【问题讨论】:

  • 您认为分配了多少内存:static int Sw_Type [];?
  • 空数组在 C 中是非法的。
  • @EugeneSh.:显示的代码中没有空数组。有一个不完整类型的数组。 (本来可以完成的。)
  • for 循环的限制是 3。因此,它使用 0-2 范围内的数组索引值。但是,您的数组只定义了一个元素。你想要:static int Sw_Type [3]; 但是,如果你增加bytes,你需要相应地调整数组。这不是一个很好的方法。 (例如)您最好在数组上方使用#define bytes 3,然后:static int Sw_Type [bytes];
  • @chux:Clang 可以稍后完成。我不确定 6.9.2 3 是打算应用于每个声明,还是应用于翻译单元末尾的已解析复合类型。

标签: c arrays static memory-address


【解决方案1】:

static int Sw_Type []; 构成暂定定义,根据 C 2018 6.9.2 2:

具有文件范围的对象的标识符声明没有初始化程序,没有存储类说明符或具有存储类说明符静态,构成暂定定义。如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,则行为与翻译单元包含该标识符的文件范围声明完全相同,复合类型为翻译单元的末尾,初始化器等于 0。

由于您的程序没有提供非暂定定义,就好像它以static int Sw_Type [] = { 0 }; 结尾。 (如果从上面引用的文本中不清楚结果确实是一个元素的数组,则在同一子句的第 5 段中的示例 2 中说明了这一点。)

因此,Sw_Type 是一个包含一个 int 的数组。它只包含元素Sw_Type[0]。 C 标准没有定义访问Sw_Type[1] 的行为。从您报告的观察结果来看,似乎Sw_Update 在内存中跟随Sw_Type,并且访问Sw_Type[1] 会导致修改Sw_Update。这种行为当然不可靠。

要使Sw_Type 更大,您必须为其声明一个大小,就像static int Sw_Type[4]; 一样。

注意:6.9.2 3 说“如果一个对象的标识符声明是一个暂定定义并且具有内部链接,则声明的类型不应是不完整的类型。”虽然这可能被解读为应用于每个声明中的声明类型,这是一个暂定定义,但我认为它可能旨在应用于对象的声明类型,一旦它的复合类型在翻译单元的末尾完全解析。在实验上,Clang 可以先接受一个不完整的类型,然后再完成它。

【讨论】:

  • 谢谢埃里克!声明尺寸解决了我的问题。我有一个关于动态大小的问题。当大小是动态的时,哪个是最好的数据结构?
  • @pranathi:对于动态大小,您无需定义数组。您定义一个指向所需类型的指针。然后,当程序运行时,您调用malloc 为所需的任意数量的对象分配空间,并将指针设置为指向该空间。
  • 感谢您的回复。我正在做嵌入式编程,我不能使用 malloc,因为这会花费我时间,而且释放也不是一件容易的事。有没有其他方法可以做到这一点?谢谢!
  • @pranathi:您要么在编译时保留内存,这需要在编译时确定大小,要么在执行时保留内存,这需要在执行时分配内存。如果您有可能需要的最大内存量,您可以在编译时保留所有这些,即使在执行时使用的内存更少。否则,您必须在执行时提供内存。也许它可能来自您系统中的堆栈,但无论如何,您必须提供内存。
  • 谢谢!这有帮助!
【解决方案2】:

所以我看到的问题是,当 Sw_Update 更新时,Sw_Type [1] 正在更新,我看到这两个具有相同的内存地址。

没有Sw_Type [1]。只有具有两个或更多元素的数组才有第二个条目,Sw_Type 不是具有两个或更多元素的数组。越界访问数组肯定会踩到其他对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-02
    • 1970-01-01
    • 2018-01-03
    • 2012-11-29
    • 1970-01-01
    相关资源
    最近更新 更多