Синтаксический анализ сообщения фиксированного размера с использованием массива переменной длины в C

#c

#c

Вопрос:

Моя программа на C должна анализировать сообщение фиксированной длины следующим образом:

 uint8_t message[8] = {80, 75, 73, 71, 1, 1, 1, 1};
 

другое сообщение может быть:

 uint8_t message[8] = {80, 75, 73, 71, 41, 42, 1, 1};
 

Сообщение содержит строку ASCII, а 1 показывает конец строки. Таким образом, фактическая длина первого сообщения равна 4, а второго сообщения равно 6.

Я использую этот метод для извлечения сообщения:

 1. Counting the message length
2. Initializing a variable length array with this value.
3. Using memcpy to copy the bytes.
 

Фрагмент кода

В файле библиотеки:

Подсчет длины:

 ...
#define LENGTH 100
// Global variables in library
uint8_t message[LENGTH];
uint8_t parsed_message[LENGTH];
uint8_t len = 0;
...

for (int i = 0; i < LENGTH; i  )
    {
        if (message[i] != 1)
        {
            parsed_message[i] = message[i];
            len  ;
        }
        else
        {
            parsed_message[i] = '';
            len  ;
            break;
        }

    }
 

Функции получения:

 void get_address(char * addr, int size)
{
    memcpy(addr, message, size);
}


uint8_t get_size(void)
{
    return len;
}
 

В основной функции:

 char addr[get_size()];
get_address(addr, get_size());
printf("==== %s ==== ADDRESSn", addr);
 

[Я пропустил проверки размера и null во фрагментах]

Я использую компилятор GCC и стандарт C99 в 32-разрядном микроконтроллере на базе ARM.

Мой вопрос в том, безопасен ли этот метод? Или я должен использовать другой подход.

Комментарии:

1. Для меня это выглядит нормально. И, насколько я вижу (если только в вашем разделе кода нет чего-то, что не показано), вы, вероятно, могли бы даже выполнить ту же замену на месте (то есть в message массиве). Это был бы oneliner.

2. @RobertoCaboni я имею в виду строку: char addr[get_size()];

3. О, теперь я понял. Опять же, это должно сработать. В этом случае, по моему личному мнению, вызываемая функция get_size () должна… получите размер вместо того, чтобы просто возвращать глобальную переменную, обновленную где-то еще.

4. В конце концов, я должен сказать, что трудно дать ответ на этот вопрос. Без конкретной проблемы, если это решение, похоже, работает, ответом может быть просто набор предложений по улучшению кода, что, вероятно, делает это предложение более подходящим для codereview.stackexchange.com чем за ТАК.

5. В любом случае я могу обобщить свое предложение здесь. Если вам больше не нужно исходное сообщение, вы можете просто обновить его на месте, чтобы в основном это была строка ( "PKIG" в вашем первом примере). Таким образом, ваш get_size () будет strlen () и ваш get_address () will be strcpy ()` . Вы message уже будете содержать адрес и сможете печатать напрямую без vla. Если вам все еще нужен vla, помните, что требуемый размер будет strlen (message) 1 , чтобы освободить место для строкового терминатора.

Ответ №1:

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

Комментарии:

1. Я получаю сообщение от серверной части. Но да, на самом деле это выбор, который может быть применен в источнике сообщения.