如何让C预处理器在编译期间执行代码?

时间:2011-09-30 02:09:01

标签: c++ c-preprocessor

我目前正在开发一个代码项目,要求我用这些字符串的哈希值替换某些字符串。看到这些字符串在运行时不会改变,让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;

我写了一个头文件生成器,这个项目工作正常。

最终解决方案

我决定在这个项目中使用John Purdy's perl script,因为它非常棒,并且允许我将我想要的输出直接提供给我的编译器。非常感谢,约翰。

4 个答案:

答案 0 :(得分:6)

实现此目的的一种方法是将所有字符串放入头文件中,并将其命名为:

// 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,并将内联引用的字符串替换为新的命名字符串常量。作为创建文件的另一个步骤,您可以对每个字符串进行哈希处理 - 或者您可以在创建文件后一次性使用该文件。这可以让你创建一个散列和非散列版本的文件(这可能很适合创建一个非散列的Debug版本和一个散列的Release版本。)

如果您尝试这样做,那么查找字符串的初始解析器必须处理边缘情况(注释,#include行,重复字符串等)。

答案 1 :(得分:6)

如果编译器支持此功能,则C ++ 11具有user defined literals

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) { ... }

答案 2 :(得分:0)

如果您无法让预处理器为您执行此操作,您可以先编写自己的预处理器来执行此步骤。

答案 3 :(得分:0)

没有办法强制它,但如果你的编译器足够好,它就可以做到。使用其优化选项并研究调试器中代码的反汇编,看看它们中的任何一个是否能让您实现所需。