Вот фрагмент кода из библиотеки 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);
}