Почему в макросе SUCCEEDED так много скобок? - PullRequest
6 голосов
/ 25 июня 2010

Windows SDK содержит макрос SUCCEEDED:

#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
-----------------------^-------------^-----

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

То, что я не получаю, этопочему вокруг (HRESULT)(hr) есть круглые скобки (я пометил их символом ^).hr заключен в скобки, так что может быть какая-то сложная конструкция, HRESULT заключен в скобки для формирования приведения в стиле C, тогда вся конструкция >= также заключена в скобки, так почему дополнительная пара скобок вокруг (HRESULT)(hr)

Ответы [ 8 ]

8 голосов
/ 25 июня 2010

Стандарт C ставит приведение более высокий приоритет, чем сравнение, поэтому для компилятора парены не требуются.

Тем не менее, люди читают определение макроса, и их вставка делает явный приоритет, так что людям, читающим его, очевидно, что это результат сравнения ((HRESULT) hr) с нулем, а не приведениярезультат сравнения без необходимости думать о приоритете.

5 голосов
/ 25 июня 2010

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

Чтобы уточнить, я имею в виду только круглые скобки вокруг приведенного выражения, как отмечено в вопросе. Другие необходимы (если только макрос не предназначен только для C ++, а не для C, в этом случае вы можете изменить (HRESULT)(hr) на HRESULT(hr)).

3 голосов
/ 26 июня 2010

Автор был просто тупым. Все лишние скобки (вокруг броска) делают его более трудным для визуального анализа. Любой, кто думает, что сравнение может иметь более высокий приоритет, чем приведение, должен изучить основы языка перед кодированием ... не говоря уже о здравом смысле.

3 голосов
/ 25 июня 2010

Это чтобы справиться с недостатками макросов - они являются просто заменой текста!

представьте себе следующий макрос

#define DOUBLE(x) x*2

int v = DOUBLE(1+1); // == 1+1*2 == 3. Did you expect 4?

Итак, эмпирические правила для макросов таковы:

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

Итак, лучший макрос будет:

# define DOUBLE(x) ((x) * 2)

Вы почти на месте, оставшиеся паратезы в вашем примере связаны с исполнением.


Таким образом, мы можем критиковать два момента:

Q: Почему это макрос, а не встроенная функция?
A: Обратная совместимость.В C нет встроенных функций (или, по крайней мере, их нет), использование функций для, вероятно, тысяч таких объявлений привело бы к сбою большинства компиляторов того времени.

Q: действительно ли нужны парантезы для этого конкретного макроса? A: Я не знаю.Вероятно, мне понадобится полчаса или больше, чтобы формально доказать (или опровергнуть) отсутствие разумного параметра и среды «вызова», где это имеет непреднамеренные последствия.Я предпочел бы следовать разумным рекомендациям, как упомянуто выше, и продолжать кодировать.

3 голосов
/ 25 июня 2010

Краткий ответ: кто знает, о чем думали разработчики MS.Однако скобки вокруг hr, очевидно, необходимы, поскольку hr может быть выражением, состоящим из более чем одного операнда.Насколько я вижу, круглые скобки ((HRESULT) (час)) не нужны.Вероятно, это было сделано просто из предостерегающей привычки: при работе с препроцессором лучше иметь слишком много скобок, чем слишком мало.

2 голосов
/ 25 июня 2010

Скобки гарантируют, что элементы взяты в правильном порядке.Вы не хотите, чтобы компилятор делал:

  1. (hr) >= 0

  2. преобразовать результат 1 в HRESULT.

Вместо этого вы хотите преобразовать только выражение (hr) в HRESULT, а затем сравнить его с 0.

1 голос
/ 25 июня 2010

Это должно обеспечить преобразование hr в HRESULT перед сравнением вместо HRESULT (hr> = 0).

0 голосов
/ 25 июня 2010

Чтобы убедиться, что выражение, которое расширяется от (hr), приведено к HRESULT, а затем по сравнению с 0.

...