Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;将字符数组传递给函数,对堆有效,但对堆栈无效?_C++_Arrays_Arduino_Stack_Heap Memory - Fatal编程技术网

C++ C++;将字符数组传递给函数,对堆有效,但对堆栈无效?

C++ C++;将字符数组传递给函数,对堆有效,但对堆栈无效?,c++,arrays,arduino,stack,heap-memory,C++,Arrays,Arduino,Stack,Heap Memory,我在Arduino uno上写下了这段代码,在这个过程中我学到了很多东西 这段代码可以工作,因为它从串行端口读入一个字符串,并返回一个serial.print语句 #include <Arduino.h> #include <IRLibRecv.h> #include <stdio.h> #define BAUDRATE 9600 #define debug 1 #define develop 0 #define MSG_SRL_IN_SIZE 64 bo

我在Arduino uno上写下了这段代码,在这个过程中我学到了很多东西

这段代码可以工作,因为它从串行端口读入一个字符串,并返回一个serial.print语句

#include <Arduino.h>
#include <IRLibRecv.h>
#include <stdio.h>

#define BAUDRATE 9600
#define debug 1
#define develop 0
#define MSG_SRL_IN_SIZE 64

bool checkForSerialMsgs(char *message);
void test();

int msgIndex = 0;
char message[MSG_SRL_IN_SIZE] = {0};

void setup() {
  Serial.begin(BAUDRATE);
  while (!Serial);
}

void loop() {
  // char message[MSG_SRL_IN_SIZE] = {0};
  if(checkForSerialMsgs(message)) {
    Serial.println(message);
  }

}

bool checkForSerialMsgs(char *message)
{
  bool msgComplete = false;
  while (Serial.available() > 0) {
    char buf = Serial.read();
    if (buf == '\n') {
       msgComplete = true;
       msgIndex = 0;
       break;
     }
     else if(buf == '\r') {
       continue;
     }
     else if(msgIndex < MSG_SRL_IN_SIZE && msgComplete == false) {
       message[msgIndex++] = buf;
     }
  }
  return msgComplete;
}

如果我注释掉那一行并在void loop()方法中取消注释第27行上的声明,那么我相信会在堆栈上声明缓冲区,因为它是一个局部变量

然而,那是行不通的

在这种情况下,由于缓冲区的大小是固定的,我认为在程序的生命周期中,它驻留在内存中不会有任何问题。但我将编写其他需要为Arduino创建相当大的动态数组的函数,我担心如果我这样做,很快就会得到一个碎片堆

然而,如果数组是在堆栈上创建的,我认为每次调用堆栈顶部的函数退出时,它们都会被清除干净

所以我的问题是,有没有办法在堆栈上而不是堆上创建数组

在回答之前,我经常被告知,使用更多的C++对象,比如字符串和向量,可以帮助我。但是,当我包含Arduino CPluPlus库来访问它们时,我的IDE会抛出一百条弃用错误消息,再也不会编译任何东西了。我要花上一个月的时间才能在这片土地上耕耘,所以我坚持这种更像C的方法

======================================================================

谢谢各位的回复

“描述一下那不起作用意味着什么。”

我的意思是当变量是全局变量时,我可以读取字符串 行-Serial.println(message);-在循环中(){}将其打印出来。 在loop()中创建消息数组时,消息在 是印刷的

“描述一下那不起作用意味着什么。你使用的是未初始化的 如果buf='\n'从未见过面,则在第二次和以后的调用中使用msgIndex。它是 最好在开始时重置变量。条件 msgComplete==false始终为true”

不,情况并非如此,当读入“\n”时,它被设置为true。然后,msgIndex也重置为0。有一个比赛条件。该函数在发送方完成传输之前读取字符

“堆中未分配全局字符消息”

谢谢你。我今天早上读的那篇文章似乎有 误导了我。考虑到我上次写C已经有多长时间了,这并不难 或者C++ bool checkForSerialMsgs(char*消息)总是可疑:要么应该是常量,要么缺少大小;函数无法猜测数组大小

当我在谷歌上搜索如何做到这一点时,我遇到了一些类似的评论,我不明白为什么这应该是常量。或者说,老实说,这会有什么不同。所以我怀疑这就是解决办法所在

虽然目前函数并不关心大小。我假设如果我发送了超过64个字符,它们将被忽略,因为条件-msgIndex 我必须得出结论,我对Arduino上内存分配的误解使我走上了死胡同。如果我使用缓冲区的全局声明,那么我根本不需要指针。所以我可以用这个:

#include <Arduino.h>
// #include <EEPROM.h>
#include <IRLibRecv.h>
#include <stdio.h>
#include <ArduinoJson.h>
#include <string>

using namespace std;

#define BAUDRATE 9600
#define debug 1
#define develop 0
#define MSG_SRL_IN_SIZE 64

bool checkForSerialMsgs();

int msgIndex = 0;
char message[MSG_SRL_IN_SIZE] = {0};

void setup() {
  Serial.begin(BAUDRATE);
  while (!Serial);
}

void loop() {
  if(checkForSerialMsgs()) {
    Serial.println(message);
  }

}

bool checkForSerialMsgs()
{
  bool msgComplete = false;
  while (Serial.available() > 0) {
    char buf = Serial.read();
    if (buf == '\n') {
       msgComplete = true;
       msgIndex = 0;
       break;
     }
     else if (buf == '\r') {
       continue;
     }
     else if(msgIndex < MSG_SRL_IN_SIZE && msgComplete == false) {
       message[msgIndex++] = buf;
     }
  }
  return msgComplete;
}

#包括
//#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#定义波特率9600
#定义调试1
#定义开发0
#定义大小为64的消息\u SRL\u
bool checkForSerialMsgs();
int-msgIndex=0;
字符消息[MSG_SRL_IN_SIZE]={0};
无效设置(){
串行开始(波特率);
而(!串行);
}
void循环(){
if(checkForSerialMsgs()){
Serial.println(消息);
}
}
bool checkForSerialMsgs()
{
bool msgComplete=false;
while(Serial.available()>0){
char buf=Serial.read();
如果(buf=='\n'){
msgComplete=true;
msgIndex=0;
打破
}
else if(buf=='\r'){
继续;
}
else if(msgIndex
很抱歉浪费了大家的时间,但至少我学到了一些东西

干杯

所以这不起作用:

void loop() {
  char message[MSG_SRL_IN_SIZE] = {0};
  if(checkForSerialMsgs(message)) {
    Serial.println(message);
  }
}
为什么呢?因为每次调用
循环()
时都会创建并清除
消息。因此,它会一直忘记您写入的所有内容,并且您可能会打印最后几个字符(但由于波特率非常低,所以通常只有'\0',因为您的速度足够快,无法获得多个字符)


顺便说一句,它也在堆栈上。

描述什么是
,什么是不起作用的
意思。如果
buf=='\n'
从未见过面,则在第二次和以后的调用中使用未初始化的msgIndex。最好在开始时重置变量。条件
msgComplete==false
始终为真。堆中未分配全局
char消息
checkForSerialMsgs
显然希望在调用之间保留
消息的内容,下一次调用可以在上一次停止的地方继续。当您使用全局缓冲区调用它时,内容实际上是保留的。当你用局部变量调用它时,它们不是——你每次都会从一个填满零的缓冲区开始。事实上,正如@S.M.所指出的,全局变量不是在堆上创建的,所以你最初的担心是放错地方了。
bool checkForSerialMsgs(char*message)
总是可疑的:要么应该是常量,要么是缺少大小;函数无法猜测数组大小。
void loop() {
  char message[MSG_SRL_IN_SIZE] = {0};
  if(checkForSerialMsgs(message)) {
    Serial.println(message);
  }
}