Условный оператор должен оценить все аргументы?

Тусклый strEmpty (-1) Как Строка

8
задан xtofl 24 November 2009 в 08:00
поделиться

8 ответов

Это очевидная ошибка, вне всякого сомнения.

Цель предупреждения НЕ состоит в том, чтобы предупредить обо всех разделах программы. Это было бы слишком шумно в любой разумной программе. Вместо этого цель состоит в том, чтобы предупредить вас, когда вам нужно проверить аргумент. В этом случае вы проверили аргумент. Следовательно, компилятор должен был отметить это и заткнуться.

Техническая реализация такой функции осуществляется путем пометки переменных в ветвях кода определенными атрибутами. Один из наиболее распространенных атрибутов - это три состояния «Нулевое значение». Перед ветвью arg является внешней переменной, а arg [[Isnull]] неизвестен. Но после проверки на arg есть две ветки. В первой ветке arg [[Isnull]] истинно. Во второй ветке arg [[Isnull]] ложно.

Теперь, когда дело доходит до генерации предупреждений о делении на ноль и нулевом указателе, следует проверить атрибут [[IsNull] . Если это правда, у вас серьезное предупреждение / ошибка. Если неизвестно, вы должны сгенерировать показанное выше предупреждение - потенциальная проблема, превышающая то, что может доказать компилятор. Но в этом случае атрибут [[isNull]] имеет значение False. Компилятор, руководствуясь той же формальной логикой, что и люди, знает, что риска нет.

Но как мы узнаем, что компилятор использует такой атрибут [[Isnull]] внутри? Вспомните первый абзац: без него пришлось бы либо предупреждать всегда, либо никогда. Мы знаем, что иногда он предупреждает, поэтому должен быть атрибут [[IsNull]] .

атрибут [[isNull]] имеет значение False. Компилятор, руководствуясь той же формальной логикой, что и люди, знает, что риска нет.

Но как мы узнаем, что компилятор использует такой атрибут [[Isnull]] внутри? Вспомните первый абзац: без него пришлось бы либо предупреждать всегда, либо никогда. Мы знаем, что иногда он предупреждает, поэтому должен быть атрибут [[IsNull]] .

атрибут [[isNull]] имеет значение False. Компилятор, руководствуясь той же формальной логикой, что и люди, знает, что риска нет.

Но как мы узнаем, что компилятор использует такой атрибут [[Isnull]] внутри? Вспомните первый абзац: без него пришлось бы либо предупреждать всегда, либо никогда. Мы знаем, что иногда он предупреждает, поэтому должен быть атрибут [[IsNull]] .

4
ответ дан 5 December 2019 в 05:26
поделиться

Условный оператор не должен оценивать все аргументы. Но я считаю, что вы можете взять arg почти равным 0, поэтому arg == 0.0 будет false , но 1./arg даст результат "деление на ноль". Так что я думаю, что это предупреждение здесь полезно.

Кстати, Visual C ++ 2008 не выдает такого предупреждения.

3
ответ дан 5 December 2019 в 05:26
поделиться

operator == для чисел с плавающей запятой небезопасен (т. Е. Ему нельзя доверять из-за проблем с округлением). В данном конкретном случае это действительно безопасно, поэтому вы можете проигнорировать предупреждение, но компилятор не будет проводить такой анализ на основе оператора, результаты которого в общем случае несколько непредсказуемы.

3
ответ дан 5 December 2019 в 05:26
поделиться

Компилятор не может статически анализировать все пути кода и постоянно учитывать все возможности. Теоретически полный анализ поведения программы, просто заглянув в ее исходный код, может предоставить решение проблемы остановки, которая неразрешима. Компиляторы имеют ограниченный набор правил статического анализа для обнаружения правил. Стандарт C ++ не требует, чтобы компилятор выдавал подобные предупреждения, поэтому нет. Это не ошибка. Это больше похоже на несуществующую функцию.

11
ответ дан 5 December 2019 в 05:26
поделиться

В дополнение к другим комментариям: предупреждение генерируется компилятором, мертвая ветвь удаляется оптимизатором, который запускается позже - возможно, даже на этапе связывания.

Так что нет, это не ошибка. Предупреждение - это дополнительная услуга, предоставляемая компилятором, не предусмотренная стандартом. Это неприятный побочный эффект архитектуры компилятора / компоновщика.

0
ответ дан 5 December 2019 в 05:26
поделиться

будет сгенерирован код подразделения, отсюда и предупреждение. но ветвление никогда не будет выполнено, если arg равно 0, так что это безопасно.

3
ответ дан 5 December 2019 в 05:26
поделиться

Вы можете избежать появления предупреждения, используя специфичное для Microsoft ключевое слово __ accept . Я не уверен, можно ли связать это с условным оператором. В противном случае стоит попробовать что-нибудь вроде

if (arg == 0.0){
  return 0.0;
}
else {
__assume(arg != 0.0);
  return 1./arg;
}

. Или, конечно, просто отключите предупреждение во время этой функции с помощью соответствующей #pragma .

0
ответ дан 5 December 2019 в 05:26
поделиться

Нет, условный оператор не оценивает оба аргумента. Однако обычно сообщается о потенциальном делении на ноль, если компилятор может обнаружить такую ​​вещь. Не зря стандарт занимает ~ 2 страницы для описания поведения этого оператора.

Из N-4411:

5.16 Условный оператор

1 Группа условных выражений справа налево. Первое выражение контекстно преобразуется в логическое значение (пункт 4). Он оценивается, и если это правда, результат условного выражение - это значение второго выражение, иначе выражение третье выражение. Только один из второе и третье выражения оценен. Расчет каждого значения и побочный эффект, связанный с первым выражение упорядочивается перед каждым вычисление значения и побочный эффект связанный со вторым или третьим выражение.

Также обратите внимание:

3 В противном случае, если второй и третий операнды бывают разных типов, и либо имеет (возможно, квалифицированное резюме) тип класса, делается попытка преобразовать каждый из этих операндов в тип другого.

В приведенном вами примере один и тот же тип для второго и третьего выражений - будьте уверены, будет вычислено только первое.

7
ответ дан 5 December 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: