如何使用C/C++预处理器生成一系列随机数

3

我希望使用C预处理程序生成一系列随机数,并将它们存储在变量中供程序使用。

目标:

每次构建程序时,我都希望生成一个“独特”的随机数集。其中一小部分存储随机数的变量将被重写为有意义的(即非随机的)数字。我希望无论黑客如何调试程序或比较多个构建版本,都无法区分有意义的数字和随机数字。我希望构建过程自动化且自包含。我希望实现能够在Visual Studio和GCC之间移植。

澄清:

  1. 计算必须在编译时完成,而不是在程序执行时完成。任何调试程序的人应该只能看到一个变量被初始化为一个常量(即随机数)。
  2. 随机数应为整数。
  3. 随机数生成器应该以某种方式从__DATE____TIME__进行种子处理,以便不同的构建会产生不同的随机数。
  4. 最好能够指定随机数的范围(例如从1到100),但这不是绝对必要的。
  5. 最好能够指定要生成的随机数的总数(例如声明1000个变量并将每个变量初始化为随机数),但这也不是绝对必要的。

到目前为止的尝试:

  1. Previous thread on arithmetic in the preprocessor: Can the C preprocessor perform integer arithmetic? The take-away is that the #if condition can evaluate arithmetic.
  2. Googling reveals that besides arithmetic, shift and bit operations can also be evaluated by the #if. I have confirmed this with Visual Studio C++.
  3. Candidates for simple random number generators: http://www.ciphersbyritter.com/NEWS4/RANDC.HTM#369B5E30.65A55FD1@stat.fsu.edu Any one of these generators, or any generator that is impossible to reverse engineer from a given series of random numbers, would be fine because I don't need a particularly well behaved generator. For the sake of this exercise, we can use the following as an example:

    unsigned long jcong=380116160;
    #define CONG (jcong=69069*jcong+1234567)
    
  4. I think the basic problem is that there is state that is stored in the variable jcong between successive calls to the generator. Variable assignment is not supported in the preprocessor, as far as I know. Perhaps there is some clever recursive macro that can do the trick?

  5. The closest I could get, but not satisfying my objective of being performed by the preprocessor, is:

    unsigned long jcong=380116160;
    unsigned long randomBlock[] = {jcong=69069*jcong+1234567, jcong=69069*jcong+1234567};
    

    I have confirmed in Visual Studio C++ that this does indeed initialize the array members to different random numbers. However, the debugger still steps through the initialization.

这是一道纯编程/实现问题,所以请不要在预处理器的邪恶或打击黑客的无用性上进行说教。

你真的需要预处理器还是C++模板就可以呢? - Karoly Horvath
预处理器不是必需品。我只需要确保整个可执行文件都是“无法被黑客攻击”的。 - Dale
1
@Dale “我只需要所有东西都是‘不可破解的’” - 我有个坏消息告诉你,那是行不通的。没有任何系统是无法被攻破的。 - The Paramagnetic Croissant
我可以建议使用VS的msbuild.exe吗?因为它的构建过程是不可预测的。我可能在一次运行中构建而没有任何错误,但在下一次构建时,即使没有更改任何内容,也会产生错误。 - mr5
2个回答

4

所以,这里提供的解决方案接近要求:

// pprand.h

#include <boost/preprocessor/slot.hpp>

#ifndef PP_RAND_SEED
#define PP_RAND_SEED    (((PP_RAND_MIN + PP_RAND_MAX) * 0x1f7) ^ 0x1e3f75a9)
#endif

#define BOOST_PP_VALUE ((PP_RAND_SEED * 214013 + 2531011) % 65536)
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#undef PP_RAND_SEED
#define PP_RAND_SEED    BOOST_PP_SLOT(1)

#define BOOST_PP_VALUE (PP_RAND_MIN + PP_RAND_SEED % (PP_RAND_MAX - PP_RAND_MIN))
#include BOOST_PP_ASSIGN_SLOT(2)
#undef BOOST_PP_VALUE

#ifdef PP_RAND
#undef PP_RAND
#endif

#define PP_RAND BOOST_PP_SLOT(2)

您可以像这样使用它:
// Pseudo random number range.
#define PP_RAND_MIN 0
#define PP_RAND_MAX 100

// Pseudo random number seed.
#define PP_RAND_SEED 123
#include "pprand.h"

// Got it!
#pragma message("PP_RAND value:" _CRT_STRINGIZE(PP_RAND))

要了解更多关于这种方法的信息,请访问我的博客:http://alexander-stoyan.blogspot.com/2012/07/getting-pseudo-random-numbers-at.html


感谢您发布答案!请务必仔细阅读有关自我推广的FAQ。还请注意,每次链接到您自己的网站/产品时,必须发布免责声明。我将为您编辑所需的免责声明。 - Andrew Barber

1

你需要用一些实际可接受的半随机值替换随机生成器序列,但这部分应该很容易。

你需要在编译时使用 -DSEED=... 定义一个随机种子。 不知道如何使用 __TIME____DATE__ 因为它们是字符串。

#include <stdio.h>

template <int N>
struct Random {
    enum { value = 7 * Random<N-1>::value + 17 };
};

template <>
struct Random<1> {
    enum { value = SEED};
};

template <int N, int BEG, int END>
struct RandomIn {
    enum { value = BEG + Random<N>::value % (END-BEG) };
};

int main() {
    printf("%d %d", RandomIn<2, 5, 10>::value, RandomIn<3, 5, 10>::value);
    return 0;
}

我在想是否有一种灵活的方式来配置变量的数量?现在,我必须为每个变量硬编码一个RandomIn<N,BEG,END>。 - Dale
我不明白你的问题。它为每个N创建一个不同的随机变量。如果你需要100个,就使用100个不同的N。 - Karoly Horvath
是的,如果我想要100个变量,我可以使用100个不同的N。如果我想要1000个变量,我将不得不硬编码1000个不同的N。我想知道是否有一些机制像int x [100] vs. int x [1000]这样简单,其中单个编译时参数将控制生成多少变量和随机数。非常感谢您迄今为止的答案;我只是希望能够在其上添加一些附加的可配置性。 - Dale
在某个时候,您必须在代码中使用这些变量,然后您明确地必须编写这些N个数字...那么这有什么意义呢?您需要任意数组吗?这是您想要的吗? - Karoly Horvath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接