MISRA C:2012 Rule 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.

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

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