Разница между прагмой один раз внутри и снаружи включает в себя охранники?

Есть ли разница между размещением #pragma once внутри включенных охранников в отличие от внешних?

случай 1:

#ifndef SOME_HEADER_H
#define SOME_HEADER_H
#pragma once

случай 2:

#pragma once
#ifndef SOME_HEADER_H
#define SOME_HEADER_H

Мне просто интересно из любопытства, если есть какие-то особые случаи, когда я должен предпочесть один или другой (случай 1 или случай 2), так как я решил объединить оба (прагма и защита заголовков) в моем коде.

EDIT:

Я думаю, вы, ребята, неверно истолковываете мой вопрос... Я спрашиваю о местоположении pragma once, а не о прагме, когда-то -vs- защитники заголовков.

Ответ 1

Там тонкая разница в том, что если SOME_HEADER_H уже определен до включения заголовка, то во втором случае препроцессор будет обрабатывать #pragma once, а в первом случае он не будет.

Вы увидите функциональную разницу, если вы #undef SOME_HEADER_H и снова включите файл тем же TU:

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

Теперь, в случае 1, у меня есть все определения из файла заголовка. В случае 2 я этого не делаю.

Даже без #undef вы могли бы увидеть разницу в времени предварительной обработки из-за игнорирования #pragma once в случае 1. Это до реализации.

Я могу думать о двух правдоподобных способах, которые он мог бы определить до первого включения этого заголовочного файла:

  • (очевидный), полностью отдельный файл определяет его, преднамеренно или случайным совпадением имен,
  • копия этого файла уже определила его. В зависимости от реализации, которая может включать случай, когда этот файл участвует в одном TU под двумя разными именами файлов, например. из-за символической связи или слияния файловой системы. Если ваша реализация поддерживает #pragma once, и вы внимательно изучите ее документацию, вы можете найти окончательное утверждение о том, применяется ли оптимизация по пути, по которому этот файл включен, или путем сравнения чего-то, что идентифицирует хранилище файлов, как индекс inode. Если последнее, вы даже можете выяснить, есть ли еще мошенники, которые можно было бы вытащить, чтобы обмануть препроцессор, например удаленный монтаж локальной файловой системы, чтобы скрыть, что он "тот же файл действительно"...

Используемый в ожидаемом режиме, однако, нет никакой разницы при условии, что реализация рассматривает #pragma once так, как это определяет Microsoft. Пока он обрабатывается, а не пропускается, он маркирует содержащийся файл для оптимизации, поэтому не имеет значения, будет ли он обрабатываться на втором проходе через файл - второго прохода не будет.

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

Ответ 2

Они избыточны.

#pragma once не поддерживается всеми компиляторами, в то время как включают защиту. Просто используйте охранники. Компиляторы, такие как gcc, достаточно умны, чтобы понять, включают ли охранники и даже не открывают файл снова.

Ответ 3

Чтобы ответить на ваш вопрос:

Случай 1:

Компилятор проверяет, установлена ​​ли константа препроцессора или нет, если она не определена, а затем проверьте директиву #pragma oñce. Скорее всего, это хэш-поиск по строке "SOME_HEADER_H", чтобы узнать, было ли оно определено или нет, прежде чем делать другой поиск хэша на текущем имени файла (вероятно, константа __ FILE __, заданная препроцессором). Поэтому, если файл никогда не читался, у нас есть два поиска хэша и два хэша, если файл был прочитан только одним поиском хэша.

Случай 2:

Это, очевидно, то же самое, что и случай 1, но в противоположном порядке. Таким образом, единственное, что мы можем сравнить, это длина хэш-ключей, используемых в качестве поиска. В зависимости от пути к текущему файлу заголовка, т.е. Длины пути, поиск хэшей для директивы #pragma once может быть более дорогим для вычисления. Если имя файла "C:\dude.h", оно короче, чем "SOME_HEADER_H".

Итак, я думаю, вкратце. Нет. Нет особого случая, когда случай 1 был бы более выгоден, чем случай 2 или наоборот. По крайней мере, не кричите Хереке;)

Приветствия