Как заставить препроцессор C выполнять код во время компиляции?
В настоящее время я работаю над проектом кода, который требует от меня заменить определенные строки хэшами этих строк. Поскольку эти строки не будут меняться во время выполнения, было бы выгодно, чтобы препроцессор c запускал мою хэш-функцию для каждой строки, которую я объявляю хэшированной во время компиляции.
есть ли способ получить C препроцессор для запуска моей хэш-функции во время компиляции?
Я знаю, что это не работает так, как я описано выше, но чтобы получить представление о том, куда я иду, вот некоторый псевдокод, который использует макрос. Представьте, что вместо простого расширения макроса препроцессор запустил хэш-функцию и расширил ее до возвращаемого значения этой хэш-функции:
#include <iostream>
#include <string>
#define U64_HASH(inputString) getU64HashCode(inputString)
//my hash function
unsigned long long getU64HashCode (string inputString)
{
/*code*/
}
int main()
{
cout << U64_HASH("thanks for helping me") << endl;
return 0;
}
опять же, в идеале cout << U64_HASH("thanks for helping me") << endl;
будет увеличен до cout << 12223622566970860302 << endl;
я написал генератор заголовочных файлов, и это отлично работает для этого проекта.
финал Решение
я решил использовать Перл-скрипт Джона Перди для этого проекта,так как это просто потрясающе, и позволяет мне кормить вывод, который я хочу непосредственно моему компилятору. Большое спасибо, Джон.
4 ответов
один из способов сделать это-поместить все ваши строки в файл заголовка и назвать их:
// StringHeader.h
#define helloWorld "Hello World"
#define error_invalid_input "Error: Invalid Input"
#define this_could_get_tedious "this could get tedious"
затем вы можете использовать эти строки:
#include "StringHeader.h"
std::cout << this_could_get_tedious << std::endl;
затем вы можете запустить программу на вашем StringHeader.h
для хэша каждой строки и создания файла заголовка замены:
// Generated StringHeader.h
#define helloWorld 097148937421
#define error_invalid_input 014782672317
#define this_could_get_tedious 894792738384
это выглядит очень ручным и утомительным, сначала, но есть способы автоматизировать его.
например, вы можете написать что - то, чтобы разобрать исходный код, ища " цитата струнные." Тогда он мог бы назвать каждую строку, записать ее в один StringHeader.h
и замените встроенную строку с кавычками новой именованной Строковой константой. В качестве дополнительного шага при создании файла вы можете хэшировать каждую строку - или вы можете иметь файл за один раз после его создания. Это может позволить вам создать хэшированную и не хэшированную версию файла (что может быть полезно для создания не хэшированной отладочной версии и хэшированной версии выпуска).
если вы попробуете это, ваш инициал парсер для поиска строк должен будет обрабатывать крайние случаи (комментарии, #include строки, дублированные строки и т. д.).
если компилятор когда-либо поддерживает это, C++11 имеет пользовательские литералы:
constexpr unsigned long long operator "" U64_HASH_(
const char *literal_string) { ... }
#define U64_HASH(inputString) inputString U64_HASH_
или constexpr
:
constexpr unsigned long long operator "" U64_HASH(
const char *literal_string) { ... }
Если вы не можете заставить предварительный процессор сделать это за вас, вы можете написать свой собственный предварительный процессор, чтобы сделать этот шаг первым.
нет способа заставить его, но если ваш компилятор достаточно хорош, он может это сделать. Играйте с его параметрами оптимизации и изучите разборку кода в отладчике, чтобы узнать, позволяет ли какой-либо из них достичь желаемого.