2011-03-21 15 views
10

¿Hay alguna diferencia entre colocar el #pragma once dentro de las protecciones incluidas en lugar de afuera?¿La diferencia entre pragma una vez adentro y afuera incluye guardias?

caso 1:

#ifndef SOME_HEADER_H 
#define SOME_HEADER_H 
#pragma once 

el caso 2:

#pragma once 
#ifndef SOME_HEADER_H 
#define SOME_HEADER_H 

Me pregunto por curiosidad si hay algún caso especial donde debería preferir uno u otro (caso 1 o el caso 2) ya que he decidido combinar ambos (pragma y guardias de encabezado) en mi código.

EDIT:

creo que ustedes están malinterpretando mi pregunta ... Estoy pidiendo sobre la ubicación de pragma once, no pragma guardias de cabecera una vez -vs-.

+1

Es bastante redundante incluir ambos, ¿no crees? Solo usaría las definiciones para verificar. –

+2

posible duplicado de [#pragma una vez vs incluir guardias?] (Http://stackoverflow.com/questions/1143936/pragma-once-vs-include-guards) – Jon

+2

@Tim: no son redundantes en un compilador que reconoce "pragma una vez", pero no realiza la optimización inteligente que hace gcc, para detectar cuándo las protecciones de los encabezados no le permiten volver a visitar el archivo. Al menos algunas versiones de MSVC se encuentran en ese estado, no se conocen las últimas. –

Respuesta

6

Hay una diferencia sutil en que si SOME_HEADER_H ya se ha definido antes se incluye la cabecera, a continuación, en el segundo caso el preprocesador procesará la #pragma once, y en el primero caso no lo hará

verás una diferencia funcional si #undef SOME_HEADER_H e incluir el archivo de nuevo por el mismo TU:

#define SOME_HEADER_H 
#include "some_header.h" 
#undef SOME_HEADER_H 
#include "some_header.h" 

Ahora, en el caso 1 Tengo todas las definiciones del archivo de cabecera. En el caso 2, yo no.

Incluso sin el #undef, es posible que vea una diferencia en el tiempo de preprocesamiento debido a que el #pragma once se ha ignorado en el caso 1. Eso depende de la implementación.

puedo pensar en dos maneras plausibles que ya se podría definir antes de la primera inclusión de este archivo de cabecera:

  • (la más obvia) un archivo completamente separado define, ya sea deliberadamente o por nombre de choque accidental ,
  • una copia de este archivo ya lo ha definido. Dependiendo de la implementación que pueda incluir el caso donde este archivo se involucra en la misma TU bajo dos nombres de archivo diferentes, p. debido a un enlace simbólico o fusión del sistema de archivos. Si su implementación es compatible con #pragma once, y examina su documentación detenidamente, puede encontrar una declaración definitiva sobre si la optimización se aplica por la ruta en la que se incluye el archivo, o por comparación de algo que identifica el almacenamiento de un archivo, como número de inodo Si es este último, incluso podrá averiguar si todavía hay estafas que podrían ser engañadas para engañar al preprocesador, como el montaje remoto de un sistema de archivos local para ocultar que es "el mismo archivo realmente" ...

Aunque se usa de la manera esperada, no hay diferencia siempre que la implementación trate #pragma once de la manera en que Microsoft lo define. Siempre que se procese en lugar de omitirse, marcará el archivo que contiene la optimización, por lo que no importa si se procesará o no en un segundo pase a través del archivo; el segundo pase no ocurrirá.

Y, por supuesto, dado que el pragma no es estándar, al menos en teoría podría tener un significado completamente diferente en diferentes implementaciones, en cuyo caso podría importar cuándo y cuántas veces se procesa. En la práctica, uno pensaría que nadie hará eso.

5

Son redundantes.

#pragma once no es compatible con todos los compiladores, mientras que incluye guardias. Sólo use incluir guardias. Los compiladores como gcc son lo suficientemente inteligentes como para comprender incluyen guardias y ni siquiera vuelven a abrir el archivo.

+1

Aunque, para fines prácticos, '#pragma once' es compatible con todos los compiladores notables. – zneak

1

Para responder a su pregunta:

Caso 1:

El compilador comprobará si la constante de preprocesador se establece o no, si no lo definen a continuación, compruebe la directiva #pragma once. Lo más probable es que sea una búsqueda hash en la cadena "SOME_HEADER_H" para saber si está definida o no antes de realizar otra búsqueda hash en el nombre del archivo actual (probablemente la constante __ FILE __ establecida por el preprocesador). Entonces, si el archivo nunca se ha leído, tenemos dos búsquedas de hash y dos hash de guardado, si el archivo se ha leído solo una búsqueda de hash.

Caso 2:

Esto es, obviamente, lo mismo que el caso 1, pero en orden inverso. Entonces, lo único que podemos comparar es la longitud de las teclas hash para usar como búsqueda. Dependiendo de la ruta al archivo de cabecera actual, es decir, la longitud de la ruta, la búsqueda hash de la directiva #pragma once podría ser más costosa de calcular. Si el nombre del archivo es "C: \ dude.h", es más corto que "SOME_HEADER_H".

Así que supongo que en resumen. No. No hay ningún caso especial en el que el Caso 1 sea más beneficioso que el Caso 2 o viceversa. Al menos no gritar Heureka sobre;)

Saludos

Cuestiones relacionadas