为什么索引 1 处的数组在我的编译器中被重置? (未定义的行为)

Why is the array at Index 1 is resetting in my compiler? (Undefined Behavior)

我不明白为什么我的编译器 (Microchip XC16) 提供的结果与其他编译器不同。

下面是我在通用机器上而非仅在我使用的 pic33fj256gp710 上转换为 运行 的示例代码。当 运行 在图片上添加代码(代码示例 2)时,我得到了不同的结果,其中第一个数组索引被重置为 0(结果 2)。

本质上,这个想法是通过串行端口获取一个字符串命令,并通过分解一个字符串并对其进行排序来基于此配置设备。

这是因为编译器最初传递一个指向值的指针直到字符串被清除而不是传递值本身吗?如果是这种情况,我如何强制编译器自己传递值?

代码示例 1:

char receive_data_2[100] = "XXXX,1,4,20,33,34";

int m = 4;
char intext[10];
int output_values[10];

int number_of_logger_selections = 0;
while(receive_data_2[m] != ' ' && number_of_logger_selections < 10)
{
    int a = 0;
    m++;
    strcpy(intext, "          ");
    do
    { // get parameter number
        intext[a++] = receive_data_2[m++];
    } while(receive_data_2[m] != ',' && receive_data_2[m] != ' ');

    output_values[number_of_logger_selections] = atoi(intext); // save output number to mark 'x'

    printf
        ("\nvalue at output_values[%d] = %d, intext = %s, translated to %d\r\n\n",
         number_of_logger_selections,
         output_values[number_of_logger_selections], intext, atoi(intext));

    number_of_logger_selections++;

    int i;
    for(i = 0; i < number_of_logger_selections; i++)
    {
        printf("value at output_values[%d] = %d\r\n", i, output_values[i]);
    }
}

结果 1:

value at output_values[0] = 1, intext = 1         , translated to 1

value at output_values[0] = 1

value at output_values[1] = 4, intext = 4         , translated to 4

value at output_values[0] = 1
value at output_values[1] = 4

value at output_values[2] = 20, intext = 20        , translated to 20

value at output_values[0] = 1
value at output_values[1] = 4
value at output_values[2] = 20

value at output_values[3] = 33, intext = 33        , translated to 33

value at output_values[0] = 1
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33

value at output_values[4] = 34, intext = 34, translated to 34

value at output_values[0] = 1
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33
value at output_values[4] = 34

代码示例 2:

int m = 4;
        char intext[10];
        int output_values[10];

        number_of_logger_selections = 0;
        while(receive_data_2[m] != ' ' && number_of_logger_selections < 10)
        {
            int a = 0;
            m++;
            strcpy(intext, "          ");
            do
            { // get parameter number
                intext[a++] = receive_data_2[m++];
            } while(receive_data_2[m] != ',' && receive_data_2[m] != ' ');

            output_values[number_of_logger_selections] = atoi(intext); // save output number to mark 'x'

            sprintf(transfer_data_2, "\nvalue at output_values[%d] = %d, intext = %s, translated to %d\r\n\n", number_of_logger_selections, output_values[number_of_logger_selections], intext, atoi(intext));
            SendSerialUserData(ANSI);

            number_of_logger_selections++;

            int i;
            for(i = 0; i < number_of_logger_selections; i++)
            {
                sprintf(transfer_data_2, "value at output_values[%d] = %d\r\n", i, output_values[i]);
                SendSerialUserData(ANSI);
            }
        }

结果 2:

value at output_values[0] = 1, intext = 1         , translated to 1

value at output_values[0] = 1

value at output_values[1] = 4, intext = 4         , translated to 4

value at output_values[0] = 0
value at output_values[1] = 4

value at output_values[2] = 20, intext = 20        , translated to 20

value at output_values[0] = 0
value at output_values[1] = 4
value at output_values[2] = 20

value at output_values[3] = 33, intext = 33        , translated to 33

value at output_values[0] = 0
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33

value at output_values[4] = 34, intext = 34        , translated to 34

value at output_values[0] = 0
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33
value at output_values[4] = 34

intext 是一个只有 10 个字节长的缓冲区,但是您要将 11 个字节复制到其中(10 个空格 + 1 个 NUL 终止符)。因此,您会得到未定义的行为,并且终止符可能会覆盖内存中缓冲区后面的任何内容。那是什么确实取决于体系结构、编译器等,这可以解释为什么当 运行 在不同的硬件上时你会看到差异。但请记住,未定义行为是未定义的,任何事情都可能发生。

您的代码包含未定义的行为。

char intext[10];

可以容纳 10 个字节,但是

strcpy(intext, "          ");

将复制 10 个空格和一个字符串终止符。

下面的内容可能看起来很奇怪或不合逻辑,但这是 UB 的一个特征 - 故障出现在与发生错误的地方不同的地方。