Есть ли лучший способ изменения массивов из функции в C? - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь создать отформатированную строку, однако я не знаю, почему я не могу напечатать глобальный массив, который я изменил внутри функции. Также странным является то, что я не могу получить доступ только к определенному глобальному массиву (rand_session_key)другие глобальные массивы ведут себя как обычно (аналогичные операции выполняются с ними, за исключением того, что их размер варьируется), и я могу получить доступ к их значению должным образом.Этот код запускается на esp32 (DOIT Dev Kit V1) (с Arduino-Core), когда я запускаю эту программу на своем компьютере (изменяя несколько функций и т. Д.), Результат, который я ожидаю, я думаю, я перекрываю символыв памяти или неправильном доступе к нему, но если бы это было так, я бы не дал ожидаемого результата на моем компьютере.

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

char persistent_peripheral_id[] = "FRUCTOSE96";
char rand_session_iden[7] = {'\0'};
char rand_session_key[17] = {'\0'};
char rand_session_channel[3] = {'\0'};

char *generate_random_session_identifier(char *rand_session_iden_local)
{
    srand(time(NULL));
    int counter = 0;
    for (counter = 0; counter < 6; counter++)
        *(rand_session_iden_local + counter) = (random(10) % ('~' - ' ')) + 'k';
    rand_session_iden_local[counter] = '\0';
    printf("Identifier : %s\n", rand_session_iden); //acessing global defintion of array everything is good until here
    return &rand_session_iden_local[0];
}

char *generate_random_session_key(char *rand_session_key_local)
{
    srand(time(NULL));
    int counter = 0;
    for (counter = 0; counter < 16; counter++)
        *(rand_session_key_local + counter) = (random(10) % ('~' - ' ')) + 'b';
    rand_session_key_local[counter] = '\0';
    printf("Key : %s\n", rand_session_key);//acessing global defintion of array everything is good until here
    return &rand_session_key_local[0];
}

char *generate_random_session_channel(char *rand_session_channel_local)
{
    srand(time(NULL));
    int channel_value = random(100);
    sprintf(rand_session_channel_local, "%03ld", channel_value);
    printf("Channel : %s\n", rand_session_channel);//acessing global defintion of array everything is good until here
    return &rand_session_channel_local[0];
}

void begin_exchange_package()
{
    //If this does not works here (observe rand_session_key) , it will not work for sprintf also ??
    printf("\n %s-%s-%s-%s \n", (char *)persistent_peripheral_id,
           generate_random_session_identifier(rand_session_iden),
           generate_random_session_key(rand_session_key),
           generate_random_session_channel(rand_session_channel));

    //Notice it prints here ????
    printf("\n %s \n",generate_random_session_key(rand_session_key));
    Serial.println("Done");


    //sprintf((char *)plain_text_package, "{\"p\":\"%s\",\"r\":\"%s\",\"k\":\"%s\",\"c\":\"%s\"}", (char *)persistent_peripheral_id,(char *)rand_session_iden, (char *)rand_session_key , (char *)rand_session_channel);

}

void setup()
{
    Serial.begin(115200);
    begin_exchange_package();
}

void loop()
{
}

Вывод FRUCTOSE96-tnltkp - 094 Где я ожидал все4 массива для печати?но он печатает отдельно, мой массив завершается неправильно?также логика назначения случайного символа всегда будет приводить к печатному символу ASCII (я узнал об этом на форуме на сайте esp32)

1 Ответ

1 голос
/ 03 июля 2019

Этот код ...

    sprintf(rand_session_channel_local, "%03ld", channel_value);

... требует rand_session_channel_local, чтобы указывать на массив не менее четырех символов, поскольку по желаниювыведите как минимум три цифры плюс разделитель строк.Массив, на который он указывает, rand_session_channel, имеет длину всего три символа.Результирующее поведение не определено.

Наблюдаемое проявление UB согласуется с глобальными массивами, размещаемыми в памяти, так что rand_session_key сразу следует за rand_session_channel, так что переполнение последнего означает, что терминатор строкизаписывается в позицию 0 первого, что делает его пустой строкой.Однако обратите внимание, что вы не можете полагаться на предсказание проявлений УБ, и, как правило, он не очень полезен для их анализа.Вместо этого избегайте упражнений UB.

Непонятно, какую функцию random вы используете, поскольку стандартная библиотека C не принимает аргумент, но если ваш аргумент задает exclusive upperзатем вы можете просто изменить формат sprintf на "%02ld".Или увеличьте размер rand_session_channel как минимум до 4.

...