Предупреждение MISRA <Сложное выражение неявно преобразуется в другие существенные типы.> - PullRequest
0 голосов
/ 11 июля 2019

MISRA C ++ правило: 5_0_3

Пробовал с одним из статических анализаторов инструментов, совместимых с MISRA, и не смог его разрешить.

#include<iostream>
#include<stdlib.h>

using namespace std;

int main()
{
    uint32_t num = 0U;
    bool Flag =false;

    num |= (Flag ? (0b10 << 10):(0b00 << 10));
}

Пожалуйста, помогите решить эту проблему. Сообщения об ошибках: 1. Непостоянные операнды к этому двоичному побитовому оператору имеют различные существенные типы. 2. Это сложное выражение неявно преобразуется в другой существенный тип.

1 Ответ

1 голос
/ 19 июля 2019

Прежде всего, синтаксис 0b является нестандартным, поэтому пока неизвестно, что он будет делать.Один только этот синтаксис является нарушением MISRA;Я бы рекомендовал вместо этого использовать шестнадцатеричные константы.Во всяком случае, ваш код не должен содержать никаких «магических чисел».

Если мы предположим, что ваш компилятор обрабатывает нестандартные 0b целочисленные константы так же, как и обычные десятичные целочисленные константы, то их тип равен (подписано) int.Результатом вашей операции является подписанное int, «по существу подписанное», как называет его MISRA.Но вы сохраняете его в uin32_t, который по существу не имеет знака, что является нарушением MISRA и причиной ошибки.

Обратите внимание, что у операторов сдвига всегда есть тип левого операнда, который повышается до целого числа.Так что писать что-то вроде 0b10 << 10u не поможет.Как правило, никогда не использует побитовые операторы для подписанных операндов.

Также обратите внимание, что ?: своеобразно, поскольку содержит неявное преобразование 2-го и 3-го операндов - онисбалансированный к тому же типу (согласно «обычным арифметическим преобразованиям»).Это может привести к незначительным ошибкам, поэтому лучше не указывать ?: при использовании небольших целочисленных типов или типов со знаком (или, если применимо, MISRA).

Я бы также рекомендовал переписатькод для чего-то с меньшим количеством «магических чисел»:

#define MASK_SOMETHING  (0x2u << 10) // give this some meaningful name
#define MASK_EMPTY      (0x0u << 10) // give this some meaningful name

uint32_t num = 0U;
bool Flag = false;

...

if(Flag)
{
  num |= MASK_SOMETHING;
}

Очевидно, что поразрядное ИЛИ против нуля не очень важно, может быть, вы хотели очистить биты вместо этого, если флаг не установлен?В этом случае вам нужно else { num &= ~MASK_EMPTY; }.

(Это также можно оптимизировать, чтобы избавиться от ветви.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...