Уничтожается ли локальная структурная переменная?

Для радиочастотного проекта мне нужно разделить полезную нагрузку на максимальный заранее определенный размер блока. Для этого я создал структуру RFmsg.

Необъяснимая часть, в которой мне нужна помощь, заключается в том, почему, когда я создаю локальный экземпляр RFmsg, его содержимое остается в такте после вызова функции? является ли это структурной "вещью"? или что- то еще, что я упускаю из виду?

Чтобы решить эту проблему, я знаю, что удаление содержимого структуры после инициализации решит эту проблему, но я хочу быть уверенным.

для этого я делюсь минимальным кодом, который:

  1. void newMSG(char * msg) имитирует разделяющую часть длинного ввода msg.
  2. void printStrcut_content(RFmsg и _payload) печатает содержимое структуры.
  3. выходные данные показывают, что только после загрузки его содержимое является тарабарщиной, но после этого оно показывает содержимое последнего обновления структуры.

КОД:

#include <Arduino.h>
#define MSG_LEN 10
#define DEVNAME_LEN 8

char *devName = "TEST";

struct RFmsg
{
    int msg_num;
    int tot_msgs;
    int tot_len;
    char payload[MSG_LEN];
    char dev_name[DEVNAME_LEN];
};

void newMSG(char *msg)
{
    RFmsg _payload;
    printStrcut_content(_payload);

    _payload.tot_len = strlen(msg);
    strcpy(_payload.dev_name, devName);
    _payload.tot_msgs = (int)(_payload.tot_len / MSG_LEN);

    if (_payload.tot_len % MSG_LEN > 0)
    {
        _payload.tot_msgs++;
    }

    for (uint8_t i = 0; i < _payload.tot_msgs; i++)
    {
        strcpy(_payload.payload, "");
        for (uint8_t n = 0; n < MSG_LEN; n++)
        {
            _payload.payload[n] = (char)msg[n + i * MSG_LEN];
        }
        _payload.payload[MSG_LEN] = '\0';

        Serial.print("chunk #");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(_payload.payload);
    }
}
void printStrcut_content(RFmsg &_payload)
{
    Serial.print("LEN: ");
    Serial.println(_payload.tot_len);
    Serial.print("PAyLOAD: ");
    Serial.println(_payload.payload);
    Serial.print("name: ");
    Serial.println(_payload.dev_name);
    Serial.print("tot_msgs: ");
    Serial.println(_payload.tot_msgs);
}

void setup()
{
    Serial.begin(115200);
    while (!Serial)
        ;
    Serial.println("\nStart");
}
void loop()
{
    newMSG("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    delay(5000);
}

РЕЗУЛЬТАТ:

Start
LEN: 36
PAyLOAD: UVWXYZ
name: 
tot_msgs: 4
chunk #0: 1234567890
chunk #1: ABCDEFGHIJ
chunk #2: KLMNOPQRST
chunk #3: UVWXYZ
LEN: 36
PAyLOAD: UVWXYZ
name: 
tot_msgs: 4
chunk #0: 1234567890
chunk #1: ABCDEFGHIJ
chunk #2: KLMNOPQRST
chunk #3: UVWXYZ
LEN: 36
PAyLOAD: UVWXYZ
name: 
tot_msgs: 4
chunk #0: 1234567890
chunk #1: ABCDEFGHIJ
chunk #2: KLMNOPQRST
chunk #3: UVWXYZ

, 👍0

Обсуждение

Я также предположил бы, что структура просто всегда находится в одном и том же пространстве памяти, сохраняя таким образом значение. Хотя вы не можете на это рассчитывать. У тебя нет никакого контроля над этим., @chrisl

@Juraj поскольку это крошечная часть гораздо большего кода, я был потрясен, увидев, что это поведение повторяется, хотя оно было намеренно сохранено каким-то образом. что бы вы посоветовали ?, @Guy . D

Просто инициализируйте переменную struct с известными значениями в начале вашей функции. Вы просто видели такое поведение, потому что вы этого не делали. Вы всегда должны инициализировать переменные в функциях. Только глобальные переменные инициализируются неявно., @chrisl


1 ответ


Лучший ответ:

3

Как описано в комментариях: ваша локальная структурная переменная, вероятно, всегда помещается в одно и то же место в памяти, и эта часть памяти не перезаписывается вашей программой. При объявлении локальных переменных они не инициализируются неявно (записываются значением). Если вы не инициализируете переменную самостоятельно, ее значением будут любые данные, находящиеся в данный момент в этом пространстве памяти.

Компилятор оптимизирует ваш код, а также решает, где разместить переменные в стеке. В этом случае он всегда размещается в одном и том же пространстве памяти, но вы не можете рассчитывать на это. Это неопределенное поведение, и любое изменение в вашей программе также может изменить этот факт. И у вас нет никакого контроля над этим.

Это причина, по которой вы всегда должны инициализировать локальные переменные перед их чтением.

что бы вы посоветовали ?

Просто инициализируйте члены этой структурной переменной перед их использованием. Установите для всех элементов значение. Вы даже можете сделать это за один шаг вместе с его объявлением:

RFmsg _payload = {1, 2, 3, "payload", "devname"};
,

Просто чтобы уточнить, неопределенное поведение не обязательно означает, что там будут нули или вообще какая-то конкретная вещь. И при определенных обстоятельствах то, что там есть, может быть тем же самым, что было там при предыдущем вызове функции. Если вы решите не утруждать себя инициализацией переменных, потому что "в прошлый раз это, казалось, сработало", вы в конечном итоге обнаружите, что изменения в вашем коде вернутся к вам., @Nick Gammon