Почему массив по индексу 1 сбрасывается в моем компиляторе? (Неопределенное поведение) - PullRequest
0 голосов
/ 30 апреля 2018

Я не понимаю, почему мой компилятор (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

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Ваш код содержит неопределенное поведение.

char intext[10];

может содержать 10 байтов, но

strcpy(intext, "          ");

скопирует 10 пробелов плюс ограничитель строки.

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

0 голосов
/ 30 апреля 2018

intext - это буфер длиной всего 10 байтов, но вы копируете в него 11 байтов (10 пробелов + 1 NUL терминатор). Поэтому вы получаете неопределенное поведение, и терминатор, вероятно, перезаписывает все, что следует за буфером в памяти. Что это действительно может зависеть от архитектуры, компилятора и т. Д., Что может объяснить, почему вы видите различия при работе на другом HW. Но помните, что неопределенное поведение не определено, и все может произойти.

...