有没有更好的方法可以在C函数中修改数组?

时间:2019-07-03 13:45:20

标签: c arduino esp32

我试图创建一个格式化的字符串,但是我不知道为什么我不能打印在函数中修改过的全局数组,而且奇怪的是我不能访问其余的特定全局数组(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()
{
}

输出为 果糖96-tnltkp--094 我希望将所有4个数组都打印在哪里?但是它确实单独打印,是我的数组以错误的方式终止了吗?分配随机字符的逻辑也总是会产生可打印的ASCII字符(我是从esp32网站上的论坛上学到的)

1 个答案:

答案 0 :(得分:1)

此代码...

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

...要求rand_session_channel_local指向至少包含四个个字符的数组,因为at将打印至少三个数字和一个字符串终止符。它指向的数组rand_session_channel只有三个字符长。结果行为是不确定的。

观察到的UB表现与在内存中布置的全局数组一致,使得rand_session_key紧随rand_session_channel之后,从而使后者溢出意味着将字符串终止符写入位置0前者,使其为空字符串。但是请注意,您不能依赖于预测UB的表现,通常也没有太多用途来分析它们。相反,避免锻炼UB。

您不清楚您使用的random函数是什么,因为C标准库不接受参数,但是如果您的参数指定了 exclusive 的上限,则可以更改sprintf格式转换为"%02ld"。或者,将rand_session_channel的大小增加到至少4。