Должен ли оператор switch всегда содержать значение по умолчанию, если он инициализирует локальные переменные? - PullRequest
1 голос
/ 04 мая 2020

Вот фрагмент кода из библиотеки FastNoise Джордана Пека . Он выдает множество предупреждений компилятора, среди которых и этот конкретный оператор switch. Здесь вы можете видеть, что переменные xs, ys и zs должны всегда получать свои значения из оператора switch, в котором отсутствует регистр по умолчанию. Обоснование состоит в том, что, поскольку m_interp является перечислением, «все» случаи явно рассматриваются в коммутаторе.

Однако при компиляции этого кода с последней версией g cc 9.3.0 (Arch * 1025) * 9.3.0-1), он предупреждает об указанных переменных (-Wmaybe-uninitialized). Действительно, это очень плохо, если когда-либо случится, что неожиданное значение достигнет этого оператора switch, потому что утомительно отлаживать код, использующий неинициализированные переменные. Например, мы не можем предположить, что xs, ys и zs инициализируются нулями. Скорее всего, они содержат мусор, прежде чем мы перейдем к оператору switch. Также было высказано предположение, что здесь виноват последний компилятор g cc, так как он не должен выдавать такое предупреждение, во-первых.

Я знаю, что подобный вопрос уже задавался, но в нем не упоминается особый случай, когда переменным присваивается их значение впервые в операторе switch. В то время как обычно может быть нормально опустить регистр по умолчанию, выполнение этого здесь может привести к очень тревожным ошибкам (неопределенное поведение). Здесь неисправна последняя версия G CC, выдающая ложно-положительное предупреждение? Или это на самом деле плохая практика программирования и виноват создатель библиотеки? Глядя на остальную часть кода, я бы сказал, что он последний, потому что в коде также используются табуляции вместо пробелов, окончания строк в стиле DOS вместо стиля Unix, и в дополнение к -Wmaybe-uninitialized у него также есть проблемы с -Wstrict-aliasing и -Wimplicit-fallthrough.

Если G CC дает здесь ложноположительный результат, то я уверен, что об этом следует сообщить соответствующим образом. Вопрос в том, действительно ли это ложноположительно?

Для протокола, я бы исправил исходное обсуждение, но, очевидно, моя репутация в Stackoverflow слишком низкая, поэтому я даже не могу комментировать. Поэтому у меня не было другого способа, кроме как создать новую топи c для обсуждения этого вопроса.


FN_DECIMAL FastNoise::SingleValue(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) const
{
    int x0 = FastFloor(x);
    int y0 = FastFloor(y);
    int z0 = FastFloor(z);
    int x1 = x0 + 1;
    int y1 = y0 + 1;
    int z1 = z0 + 1;

    FN_DECIMAL xs, ys, zs;
    switch (m_interp)
    {
    case Linear:
        xs = x - (FN_DECIMAL)x0;
        ys = y - (FN_DECIMAL)y0;
        zs = z - (FN_DECIMAL)z0;
        break;
    case Hermite:
        xs = InterpHermiteFunc(x - (FN_DECIMAL)x0);
        ys = InterpHermiteFunc(y - (FN_DECIMAL)y0);
        zs = InterpHermiteFunc(z - (FN_DECIMAL)z0);
        break;
    case Quintic:
        xs = InterpQuinticFunc(x - (FN_DECIMAL)x0);
        ys = InterpQuinticFunc(y - (FN_DECIMAL)y0);
        zs = InterpQuinticFunc(z - (FN_DECIMAL)z0);
        break;
    }

    FN_DECIMAL xf00 = Lerp(ValCoord3DFast(offset, x0, y0, z0), ValCoord3DFast(offset, x1, y0, z0), xs);
    FN_DECIMAL xf10 = Lerp(ValCoord3DFast(offset, x0, y1, z0), ValCoord3DFast(offset, x1, y1, z0), xs);
    FN_DECIMAL xf01 = Lerp(ValCoord3DFast(offset, x0, y0, z1), ValCoord3DFast(offset, x1, y0, z1), xs);
    FN_DECIMAL xf11 = Lerp(ValCoord3DFast(offset, x0, y1, z1), ValCoord3DFast(offset, x1, y1, z1), xs);

    FN_DECIMAL yf0 = Lerp(xf00, xf10, ys);
    FN_DECIMAL yf1 = Lerp(xf01, xf11, ys);

    return Lerp(yf0, yf1, zs);
}
...