【问题标题】:global pointer to array指向数组的全局指针
【发布时间】:2011-12-11 18:07:32
【问题描述】:

似乎我仍然没有正确获得 C 中的指针。

我希望全局数组(指针)j 的长度是动态的。

我有这个(Arduino)代码

unsigned int* j;

void setup() {

  Serial.begin(9600);

  initj();

  Serial.println(j[0]); //111 -> right
  Serial.println(j[0]); //768 -> wrong!
  Serial.println(j[1]); //32771 -> wrong!
}

void initj() {
  unsigned int i[2];
  i[0] = 111;
  i[1] = 222;

  j = i;

  Serial.println(j[0]); // 111 -> right
  Serial.println(j[1]); // 222 -> right
}

void loop() {
}

我怎样才能做到这一点?

提前谢谢你!

【问题讨论】:

  • “我希望全局数组(指针) j 的长度是动态的。” (强调添加)数组和指针是 不是同义词,如果你认为他们是你可能从一开始就有麻烦。是的,它们共享很多语法,是的,数组会衰减为指针,但它们是不同的东西
  • 你需要了解堆和栈的区别。尤其是退出函数时堆栈存储会发生什么。
  • 我建议先在你的桌面上学习一点 C 代码,一旦你学会了足够的东西,就去你的 Arduino(它实现了 C 或 C++ 的一个小变体)
  • @BasileStarynkevitch 在 Arduino 上编码并不难(尽管我不得不承认我的指针有问题)。还是谢谢你。

标签: c arrays global local arduino


【解决方案1】:

您的initj() 函数将j 设置为指向一个本地 数组。这个数组的生命周期仅限于函数调用本身,一旦函数返回,指针就不再有效。因此,尝试取消引用 jundefined behaviour

我不知道你到底想做什么,但三种可能性是:

  1. 改为在全局范围内声明 i
  2. i 声明为static
  3. 使用malloc动态分配数组(可能不适合嵌入式平台)。

【讨论】:

  • 感谢您的帮助!我认为如果不全局定义它的长度,就无法声明 i 全局,对吗?所以我必须去(2)!?
  • @Marcel:无论是在全局范围内定义int i[2];,还是在函数内部定义static int i[2];,有什么区别?
  • 这段代码只是一个例子。在我真正的问题中,数组的长度是从一个函数派生的(它涉及计算(全局定义的)字符串的位数等)。如何将函数的结果用于全局定义变量的长度?
【解决方案2】:

这是因为数组 i[2]initj() 函数的本地数组。因此,一旦函数返回,它就不再有效。所以指针j变成了一个悬空指针。

所以你调用了未定义的行为。

至于为什么这两行的行为方式是这样的:

Serial.println(j[0]); //111 -> right
Serial.println(j[0]); //768 -> wrong!

即使值丢失了,它们仍然碰巧在堆栈上。因此,当您在调用Serial.println 之前访问它时,您将获得“正确”的值。但是该函数调用最终会覆盖堆栈。所以在第二次调用时,它给出了错误的值。

但无论如何,它仍然是未定义的行为。任何事情都允许发生。


要解决此问题,您需要将值放在setup() 函数可见的范围内。您可以全局声明i[2],也可以在setup() 中声明并将其传递给initj() 函数。

您还可以使用malloc() 在堆内存中动态分配数组。 (请务必稍后使用free() 释放它)

【讨论】:

    【解决方案3】:

    一旦 initj 完成,它的堆栈空间就会被操作系统破坏(或者实际上,堆栈指针被移动并且 initj 的地址不再可靠)。因为i 存在于该堆栈空间中,所以i 消失了。而你只是将i 的值复制到j。所以,在 setup() 中,j 是一个悬空指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多