2016-07-17 7 views
1

Это немного меня обманывает, потому что я не вижу никаких проблем с этим кодом.Есть ли возможность деления на ноль в этом условном выражении?

В любом случае, вот загадка:

Пусть кто-то вводит случайное значение в a, b:

int foo(int a, int b) 
{ 
    return b ? (a/b): 0; 
} 

b != 0 всегда!

Возможно ли исключение целочисленного нуля?

Я начинаю думать, что это шутка, но ....

Примечание:

Этот вопрос был опубликован в конференции, есть вероятность того, что автор был специфичным для компилятора/архитектура, где это проблематично.

+1

«b! = 0 всегда!» Предоставляется (гарантировано) или вам необходимо обеспечить соблюдение? –

+0

Итак, случайным значением может быть любое значение, кроме нуля ?! –

+0

@SouravGhosh гарантировано. 'b' не может быть нулем. – Delights

ответ

4

Нет, деление на ноль здесь невозможно.

Цитирование C11, глава §6.5.15, условный оператор, (курсив мой )

Первый операнд; существует точка последовательности между ее оценкой и оценкой второго или третьего операнда (в зависимости от того, что оценивается). Второй операнд оценивается только в том случае, если первый сравнивается не равным 0; третий операнд оценивается только в том случае, если первое сравнивается с 0; [...]

Таким образом, в случае, b является 0, то выражение (a/b) не будет оцениваться.

Тем не менее, так же, как примечание:

  • Разделение является целочисленное деление.
  • Если у вас есть обертка, которая обеспечивает b != 0, то вы могли бы сократить вызов всей функции и просто написать someVar = a/b;

Кроме того, я не знаю ни архитектура, которая (возможно ) изменяет вышеупомянутое поведение.

+0

Я прочитал стандарт, но это вопрос, который кто-то задал на конференции. возможно, он был очень конкретным, я имею в виду конкретный компилятор/архитектура, где это проблематично. – Delights

+2

@Medals, тогда вы должны упомянуть об этом в своем вопросе, правильно? –

+0

@Medals: Контекст! Если речь идет о перевернутых битах/коррупции, это бесполезно, даже потенциально опасно. – Olaf

3

Там нет возможности для деления на 0 в вашем примере, но есть другого частный случай вы должны проверить: разделив INT_MIN на -1 может вызвать переполнение деления, и, как правило, вызывает фатальное исключение на оборудовании Intel, удивительное поведение, но в соответствии с C-стандартом, который указывает, что целочисленное переполнение может привести к определенному поведению.

Если вам нужно защитить от такого нежелательного поведения, вы должны особый случай эти операнды и обращаться с ними конкретно:

#include <limits.h> 

int foo(int a, int b) { 
    if (b == 0) return 0; 
    if (a == INT_MIN && b == -1) return INT_MAX; 
    return a/b; 
} 

Поскольку значения a и b могут быть обработаны с помощью внешнего источника, вам обязательно нужно беспокоиться о переполнении подразделения. Это забавная игра, в которую можно попробовать, чтобы опробовать небезопасные калькуляторы, подав им эти ценности.

+1

Это возможно только для дополнения 2s. – Olaf

+0

@ Олаф: правильно, но вряд ли спасет ОП ;-). возвращение 'INT_MAX' должно быть хорошо на других архитектурах. – chqrlie

+0

Я действительно рекомендовал либо насытить, либо использовать представление «ловушки»/ошибки на уровне приложения. В дополнении 2s «INT_MIN» будет хорошим выбором, который автоматически избежит проблемы, о которой вы указали. Но тогда код должен использовать размножение ошибок. (Обратите внимание, что с gcc вы находитесь в безопасности, так как он поддерживает только 2s-дополнения). – Olaf