c-当大小未知时,通过引用将char数组传递给函数



我正在学习指针和字符数组,想知道您是否可以帮助我在这里找到最佳解决方案。我想避免使用malloc,因此我选择通过引用将char数组传递给函数,在函数中填充值。在我的主.c 中

char saved_networks[100]; // create an array to save data
readFile123(SPIFFS, "/wifi.txt",saved_networks);
Serial.print("saved networks=");
Serial.println(saved_networks);

和功能:

void readFile123(fs::FS &fs, const char *path, char* return_data)
{

int n=0;
Serial.printf("Reading file: %sn", path);
File file = fs.open(path);
if (!file || file.isDirectory())
{
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available())
{
char c =  file.read();
delayMicroseconds(100);
Serial.print(c);
//strcat(return_data, &c); //returns meditation error
return_data[n]=c; 
n=n+1;
}
file.close();
}

在上面的程序中,我创建了一个大小为100的char数组,并将其传递给函数。在一个函数中,我读取SPIFFS文件系统中的数据,然后将在其中找到的任何字符串附加到我的char数组中。上面的代码工作,但我有3个问题:

1.为什么我不能使用strcat(return_data, &c);

导致cpu崩溃并返回错误:

Stack smashing protect failure!
abort() was called at PC 0x40137793 on core 1
ELF file SHA256: 0000000000000000 

2.为什么我不能如下声明我的char数组:char* saved_networks;。如果我这样做,我的微控制器将崩溃并返回错误:

Read from file: TGuru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled

3.解决这个问题的最佳方法是什么?由于我不知道从SPIFFS读取的数据的最大大小是多少,所以简单地声明它的大小为100可能是不够的。有什么方法可以动态地声明它吗?我想唯一的方法就是使用malloc?这是真的吗?

  1. strcat(return_data, &c)是一个<string>函数,因此,它需要实际的字符串,而不是char数组
    在您的示例中,您传递一个char的地址,该地址可以解释为大小为1的char数组。有什么区别
    字符串是以null结尾的char数组,这意味着它们的最后一个有效元素是'',该char之后的所有内容都被str函数忽略。

  2. char* saved_networks;声明一个可以存储char类型地址的变量,您仍然需要分配空间!然后,该空间的地址将被存储在saved_networks中。

  3. 在读取文件之前,您可以先了解文件的大小,也可以增量读取。由于您使用的是C++,因此您也可以使用std::string

Edit:当你传递数组的名称时,它已经是一个引用,所以我认为你已经正确地传递了它,只需要小心不要超过分配的空间(在这种情况下是100个字符(。

为了更清楚,让我给你看一些句法糖的例子:

char saved_networks[100];
saved_networks == &saved_networks[0]; // true
saved_networks[0] == *saved_networks; // true
saved_networks[50] == *(saved_networks + 50); // true
&saved_networks[50] == saved_networks + 50; // true

+50取决于数组类型:在这种情况下,它意味着50个字节,因为每个字符是1个字节。

编辑2:"h"在现实中更类似于:

char const arr[2] = {'h', ''};

这意味着"用于字符串,'用于字符!这一点很重要,因为str函数期望字符串以null终止,否则将有来自无限循环的无效内存访问。

我想这就是你所缺少的,现在你将能够更好地理解我的第一点。

传递数组的长度:

size_t len = sizeof(saved_networks)/sizeof(*saved_networks);
char *saved_networks = readFile123(SPIFFS, "/wifi.txt",saved_networks, &len);

然后确保不超过长度:

char *readFile123(fs::FS &fs, const char *path, size_t *lenp)
{
size_t chunksize = *lenp; // You can pass in chunksize you want to use
size_t n = 0;
size_t chunk_len = 0;
char *return_data = malloc(chunksize);
return_data[0]=0;
*lenp = 0;
...
while (file.available())
{
char c =  file.read();
delayMicroseconds(100);
Serial.print(c);
return_data[n]=c; 
n=n+1;
chunk_len++;
if (chunk_len == chunksize-1)
{
return_data = realloc(return_data, n+chunksize);
chunk_len = 0;
}
}
return_data[n]=0;
*lenp = n;
return return_data;
}

最新更新