exponenta event banner

MISRA C:2012 Правило 18.4

Операторы +, -, + = и - = не должны применяться к выражению типа указателя

Описание

Определение правила

Операторы +, -, + = и - = не должны применяться к выражению типа указателя.

Объяснение

Предпочтительной формой арифметики указателей является использование синтаксиса подстрочного индекса массива ptr[expr]. Этот синтаксис ясен и менее подвержен ошибкам, чем манипулирование указателями. При манипулировании указателями любое явно рассчитанное значение указателя может получить доступ к непреднамеренным или недопустимым адресам памяти. Индексирование массива также может иметь доступ к непреднамеренной или недопустимой памяти, но его легче просмотреть.

Для нового программиста C выражение ptr+1 может быть ошибочно интерпретирован как один плюс адрес ptr. Однако новый адрес памяти зависит от размера в байтах целевого объекта указателя. Эта путаница может привести к неожиданному поведению.

При использовании с осторожностью манипулирование указателем с помощью ++ может быть более естественным (например, последовательный доступ к местоположениям во время тестирования памяти).

Внедрение Polyspace

Операции с флагами Polyspace ® для указателей, например :Pointer + Integer, Integer + Pointer, Pointer - Integer.

Поиск неисправностей

Если вы ожидаете нарушения правила, но не видите его, обратитесь к разделу Нарушения стандартов кодирования не отображаются.

Примеры

развернуть все

void fun1(void){
    unsigned char arr[10];
    unsigned char *ptr;
    unsigned char index = 0U;
    
    index = index + 1U;   /* Compliant - rule only applies to pointers */
    
    arr[index] = 0U;      /* Compliant */
    ptr = &arr[5];        /* Compliant */
    ptr = arr;
    ptr++;                /* Compliant - increment operator not + */
    *(ptr + 5) = 0U;      /* Non-compliant */
    ptr[5] = 0U;          /* Compliant */
}

В этом примере показаны различные операции с указателями и массивами. Единственной операцией в этом примере, которая не соответствует, является использование + оператор непосредственно с указателем (строка 12).

void fun2(void){
    unsigned char array_2_2[2][2] = {{1U, 2U}, {4U, 5U}};
    unsigned char i = 0U;
    unsigned char j = 0U;
    unsigned char sum = 0U;
    
    for(i = 0u; i < 2U; i++){
        unsigned char *row = array_2_2[ i ];
        
        for(j = 0u; j < 2U; j++){
            sum += row[ j ];                   /* Compliant */    
        }
    }        
}

В этом примере второй for цикл использует указатель массива row в арифметическом выражении. Однако это использование совместимо, поскольку использует форму индекса массива.

void fun3(unsigned char *ptr1, unsigned char ptr2[ ]){
    ptr1++;               /* Compliant */
    ptr1 = ptr1 - 5;      /* Non-compliant */
    ptr1 -= 5;            /* Non-compliant */
    ptr1[2] = 0U;         /* Compliant */
    
    ptr2++;               /* Compliant */
    ptr2 = ptr2 + 3;      /* Non-compliant */
    ptr2 += 3;            /* Non-compliant */
    ptr2[3] = 0U;         /* Compliant */
}

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

Если ptr1 не указывает на массив по крайней мере с шестью элементами, и ptr2 не указывает на массив по крайней мере с 4 элементами, этот пример нарушает правило 18.1.

Проверить информацию

Группа: указатели и массивы
Категория: Консультационные услуги
СМЖЛ Категория: Консультативные услуги