2010-06-25 13 views
6

características del SDK de Windows tuvo éxito macro:¿Por qué hay tantos paréntesis en la macro ÉXITO?

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

claramente como con otras macros hay paréntesis para asegurar una interpretación correcta de la intención por el compilador.

Lo que no entiendo es por qué hay paréntesis alrededor de (HRESULT)(hr) (los marqué con el carácter ^). hr está entre paréntesis para que algún constructo complejo pueda estar allí, HRESULT está entre paréntesis para formar un molde de estilo C, entonces el constructo entero >= también está entre paréntesis, entonces ¿por qué el par extra de paréntesis alrededor de (HRESULT)(hr)?

+0

Disculpas por la edición hiper-pedante, pero el título de la pregunta me estaba molestando cada vez que lo vi en la página principal ... – AakashM

+0

@AakashM: Como no soy un hablante nativo de Inglés, tengo que preguntar: ¿qué la diferencia entre "llaves" y "paréntesis"? Veo frases como "necesitas apuntalar los argumentos correctamente en tu macro" de vez en cuando. ¿Por qué la palabra "llaves" no es adecuada aquí? – sharptooth

+1

@sharptooth: "llaves" a menudo, aunque no siempre, significa '{}', a veces llamado "llaves". "Paréntesis" generalmente significa '()', algunas veces llamado "corchetes redondos". "Brackets" se usa a veces para significar '[]' o '<>', algunas veces llamados "corchetes" y "corchetes angulares". Los tres términos se usan indistintamente. El inglés no es tan preciso como C++. –

Respuesta

7

El estándar C pone el fundido a una prioridad más alta que la comparación, por lo que los parens no son requerido para el compilador

Sin embargo, las personas leen la definición de la macro y al ponerlas en su lugar se hace explícita la precedencia, de modo que es obvio para las personas que la leen que es el resultado de comparar ((HRESULT) hr) con cero en lugar de arrojar el resultado de la comparación sin tener que pensar en la precedencia.

2

Las llaves se aseguran de que los elementos se toman en el orden correcto. Usted no quiere que el compilador debe hacer:

  1. (hr) >= 0

  2. resultado de convertir a 1. HRESULT.

lugar que desea convertir sólo la expresión (hr) a HRESULT, luego compararlo con 0.

+1

Claro, pero eso es lo que la precedencia del operador C y C++ hace de todos modos, y la mayoría de la gente se da cuenta de eso. –

1

Es para asegurar que hr se convierta en HRESULT antes de ser comparado, en lugar de HRESULT (hr> = 0).

+2

Las reglas de precedencia aseguran que; los paréntesis simplemente dejan en claro al lector que ese es el caso. –

0

Para asegurarse de que la expresión que se expande a partir de (hr) es fundido a HRESULT, y se comparan después con 0.

5

Los paréntesis adicionales no cambian el significado, pero hacen que la precedencia sea explícita. Sin ellos, un lector que no conocía todas las reglas de precedencia tendría que averiguar qué significaba la expresión.

Para aclarar, solo me estoy refiriendo a los paréntesis alrededor de la expresión de lanzamiento, como se indica en la pregunta. Los otros son necesarios (a menos que la macro solo se haya diseñado para C++ y no para C, en cuyo caso puede cambiar el (HRESULT)(hr) al HRESULT(hr)).

+0

-1, no es cierto. Vea el ejemplo en mi respuesta: el significado puede cambiar según los argumentos que se pasen, ya que las macros son reemplazos de texto jsut. – peterchen

+0

@peterchen: en este caso, el argumento está entre paréntesis, por lo que el significado es el mismo para cualquier expresión válida, con o sin paréntesis adicionales alrededor de la expresión moldeada. Las macros ciertamente pueden tener dificultades, pero no esta. A menos que pueda proporcionar un ejemplo de un argumento que lo rompa. –

+0

Tienes razón, Mike, ignoré la "línea divertida" debajo de su texto. Sin embargo, no se puede revocar el -1 a menos que edites. – peterchen

3

Respuesta corta: quién sabe en qué estaban pensando los desarrolladores de MS. Sin embargo, los paréntesis alrededor de hr son obviamente necesarios ya que hr podría ser una expresión que consta de más de un solo operando. Los paréntesis alrededor ((HRESULT) (hr)) son innecesarios por lo que puedo ver. Probablemente esto se haya hecho por un hábito de advertencia: cuando se trabaja con el preprocesador, es mejor tener demasiados paréntesis que muy pocos.

3

Esto es para hacer frente a las deficiencias macro - ¡son solo un reemplazo de texto!

Imagine la siguiente macro

#define DOUBLE(x) x*2 

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

Así que las reglas generales para las macros son:

  • ellos utilizan sólo si no hay otra manera de resolver su problema
  • envoltura de cada parámetro en parantheses (para evitar el problema anterior)
  • envuelve toda la expresión en parantheses (para evitar otros problemas similares)
  • hacen cada parámetro sólo se produce una vez (para evitar problemas con los efectos secundarios)

Por lo tanto, una mejor macro sería:

#define DOBLE (x) ((x) * 2)

Estás casi allí, las parantheses restantes en tu ejemplo se deben al yeso.


para que podamos criticar dos puntos:

Q: por qué es una macro, no una función en línea?
A: Compatibilidad con versiones anteriores. C no tiene funciones en línea (o al menos no lo hizo), el uso de funciones para los probablemente miles de tales declaraciones habría reducido la mayoría de los compiladores de ese momento.

Q: ¿Las parantheses son realmente necesarias para esta macro específica? A: No lo sé. Probablemente me llevaría media hora o más probar formalmente (o rechazar) que no existe un parámetro sensible y un entorno de "llamada" en el que esto tenga efectos involuntarios. Prefiero seguir las pautas sensatas como se mencionó anteriormente, y seguir codificando.

+0

A su primer ejemplo le falta la definición de 'DOUBLE' ... –

+2

Este es un buen consejo general, pero no es relevante para la pregunta; el argumento de SUCCEEDED está entre paréntesis como debería ser, como lo es toda la expresión. La pregunta es acerca de las parantheses superfluas alrededor de la expresión moldeada. –

+0

@Donal: ¿eh? es la primera línea. – peterchen

3

El autor fue simplemente estúpido. Todos los paréntesis adicionales (alrededor del elenco) hacen que sea más difícil realizar un análisis visual. Cualquiera que piense que la comparación posiblemente tenga una precedencia más alta que el casting necesita aprender los principios básicos del lenguaje antes de codificar ... sin mencionar que tiene algo de sentido común.

Cuestiones relacionadas