3

I would like to generate a series of random numbers with the C preprocessor, and store them in variables for use by my program.

OBJECTIVES:

I would like to generate a "unique" set of random numbers every time I build my program. A small subset of the variables storing the random numbers will be overwritten with meaningful (i.e. non-random) numbers. I would like it to be impossible for a hacker, by debugging the program or comparing multiple builds, to be able to differentiate the meaningful numbers from the random numbers. I would like the build process to be automated and self-contained. I would like the implementation to be portable across Visual Studio and GCC.

CLARIFICATIONS:

  1. The calculations must be done at compile time, not at program execution. Anyone debugging the program should only be able to see, for example, a variable being initialized to a constant (the random number).
  2. The random numbers should be integers.
  3. The random number generator should be seeded, in some manner, from __DATE__ and __TIME__, so that different builds will yield different random numbers.
  4. It would be preferable, but not absolutely necessary, to be able to specify a range for the random numbers (e.g. from 1 to 100).
  5. It would be preferable, but not absolutely necessary, to be able to specify the total number of random numbers to generate (e.g. declare 1000 variables and initialize each to a random number).

ATTEMPTS SO FAR:

  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.

This is a pure programming/implementation question, so please, no proselytizing on the evils of the preprocessor or the futility of fighting hackers.

Community
  • 1
  • 1
Dale
  • 31
  • 1
  • 2
  • Do you really need preprocessor or a C++ template is fine? – Karoly Horvath Jun 27 '11 at 20:06
  • The preprocessor is not a requirement. I just need it all to be "unhackable" through the executable. – Dale Jun 27 '11 at 20:22
  • 1
    @Dale "I just need it all to be "unhackable"" – I have bad news for you, that's not gonna work. No system is unbreakable. – The Paramagnetic Croissant Jul 22 '15 at 16:42
  • May I suggest VS's msbuild.exe? Cause its build process is unpredictable. I could build in one run without any error, and on the next buildm without touching anything, it would produce an error. – mr5 May 25 '17 at 05:08

2 Answers2

4

So, here is the solution that is close to requirements:

// 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)

You can use it like this:

// 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))

To read more about this approach visit my blog: http://alexander-stoyan.blogspot.com/2012/07/getting-pseudo-random-numbers-at.html

Fabio A.
  • 2,517
  • 26
  • 35
Alexander
  • 471
  • 1
  • 4
  • 6
  • Thanks for posting your answer! Please be sure to read the [FAQ on Self-Promotion](http://stackoverflow.com/faq#promotion) carefully. Also note that it is *required* that you post a disclaimer every time you link to your own site/product. I am editing in the required disclaimer for you. – Andrew Barber Dec 13 '12 at 21:32
1

You have to replace the Random generator sequence with something that actually generates acceptable semi-random values, but that part should be easy.

You have to define a random seed with -DSEED=... at compilation. No idea how to do that with __TIME__ and __DATE__ because they are strings.

#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;
}
Kijewski
  • 25,517
  • 12
  • 101
  • 143
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • I'm wondering if there is a way to flexibly configure the number of variables? As it is now, I must hard code a RandomIn for each variable. – Dale Jun 28 '11 at 16:16
  • I don't understand your question .It creates a different random variable for each N. If you need 100, use 100 different N-s. – Karoly Horvath Jun 28 '11 at 16:18
  • Yes, if I want 100 variables I can use 100 different N's. If I want 1000 variables, I would have to hard code 1000 different N's. I'm wondering if there is some mechanism as simple as, for example, int x[100] vs. int x[1000], where a single compile-time parameter would control how many variables and random numbers are generated. Thank you very much for your answer so far; I'm just hoping something can be layered on top of it for this additional configurability. – Dale Jun 29 '11 at 01:25
  • Well at some point you have to use those variables in your code and then you explicitly have to write those N numbers... so what's the point? You need any array of random variables? Is that what you want? – Karoly Horvath Jun 29 '11 at 07:43