Как сгенерировать серию случайных чисел с помощью препроцессора C / C ++

Я хотел бы сгенерировать серию случайных чисел с помощью препроцессора C и сохранить их в переменных для использования в моей программе.

ЗАДАЧИ:

Я хотел бы генерировать «уникальный» набор случайных чисел каждый раз, когда я создаю свою программу. Небольшое подмножество переменных, хранящих случайные числа, будет перезаписано значимыми (то есть неслучайными) числами. Я бы хотел, чтобы хакер, отлаживая программу или сравнивая несколько сборок, не мог отличить значимые числа от случайных. Я бы хотел, чтобы процесс сборки был автоматизированным и автономным. Я хотел бы, чтобы реализация была переносимой в Visual Studio и GCC.

РАЗЪЯСНЕНИЯ:

  1. Вычисления должны выполняться во время компиляции, а не во время выполнения программы. Любой, кто занимается отладкой программы, должен видеть, например, только то, что переменная инициализируется константой (случайным числом).
  2. Случайные числа должны быть целыми.
  3. Генератор случайных чисел должен быть каким-то образом засеян из __DATE__ и __TIME__, чтобы разные сборки давали разные случайные числа.
  4. Было бы предпочтительно, но не обязательно иметь возможность указать диапазон для случайных чисел (например, от 1 до 100).
  5. Было бы предпочтительно, но не обязательно иметь возможность указать общее количество случайных чисел для генерации (например, объявить 1000 переменных и инициализировать каждую случайным числом).

ПЫТАЕТСЯ ТАКОЕ:

  1. Предыдущая тема по арифметике в препроцессоре: Может ли препроцессор C выполнять целочисленную арифметику? Вывод состоит в том, что условие #if может оценивать арифметические операции.
  2. Поиск в Google показывает, что помимо арифметических операций сдвиг и бит также могут оцениваться с помощью #if. Я подтвердил это с помощью Visual Studio C ++.
  3. Кандидаты в простые генераторы случайных чисел: http://www.ciphersbyritter.com/NEWS4/RANDC.HTM#[email protected] Подойдет любой из этих генераторов или любой генератор, который невозможно реконструировать из данной серии случайных чисел. потому что мне не нужен особенно хорошо работающий генератор. Для этого упражнения мы можем использовать в качестве примера следующее:

    unsigned long jcong=380116160;
    #define CONG (jcong=69069*jcong+1234567)
    
  4. Я думаю, что основная проблема заключается в том, что между последовательными вызовами генератора в переменной jcong сохраняется состояние. Насколько мне известно, назначение переменных не поддерживается препроцессором. Может быть, есть какой-нибудь умный рекурсивный макрос, который поможет?

  5. Самое близкое, что я мог получить, но не удовлетворяющее моей цели выполнения препроцессором, это:

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

    Я подтвердил в Visual Studio C ++, что это действительно инициализирует элементы массива разными случайными числами. Однако отладчик по-прежнему выполняет инициализацию.

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


person Dale    schedule 27.06.2011    source источник
comment
Вам действительно нужен препроцессор или шаблон C ++ подойдет?   -  person Karoly Horvath    schedule 28.06.2011
comment
Препроцессор не является обязательным. Мне просто нужно, чтобы все это нельзя было взломать через исполняемый файл.   -  person Dale    schedule 28.06.2011
comment
@ Дейл, мне просто нужно, чтобы все это было невозможно взломать - у меня для тебя плохие новости, это не сработает. Нет системы, которую нельзя сломать.   -  person The Paramagnetic Croissant    schedule 22.07.2015
comment
Могу я предложить VS msbuild.exe? Потому что процесс его сборки непредсказуем. Я мог бы выполнить сборку за один прогон без каких-либо ошибок, а на следующей сборке, ничего не касаясь, это выдало бы ошибку.   -  person mr5    schedule 25.05.2017


Ответы (2)


Итак, вот решение, близкое к требованиям:

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

person Alexander    schedule 13.07.2012
comment
Спасибо, что разместили свой ответ! Не забудьте внимательно прочитать FAQ по саморекламе. Также обратите внимание, что требуется, чтобы вы публиковали отказ от ответственности каждый раз, когда вы ссылаетесь на свой собственный сайт / продукт. Я редактирую для вас требуемый отказ от ответственности. - person Andrew Barber; 14.12.2012

Вы должны заменить последовательность генератора случайных чисел чем-то, что на самом деле генерирует приемлемые полуслучайные значения, но эта часть должна быть простой.

Вы должны определить случайное начальное число с -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;
}
person Karoly Horvath    schedule 27.06.2011
comment
Интересно, а есть ли способ гибко настроить количество переменных? Сейчас я должен жестко закодировать RandomIn ‹N, BEG, END› для каждой переменной. - person Dale; 28.06.2011
comment
Я не понимаю ваш вопрос. Он создает разные случайные переменные для каждого N. Если вам нужно 100, используйте 100 разных N. - person Karoly Horvath; 28.06.2011
comment
Да, если мне нужно 100 переменных, я могу использовать 100 разных N. Если мне нужно 1000 переменных, мне придется жестко закодировать 1000 разных N. Мне интересно, есть ли такой простой механизм, как, например, int x [100] vs. int x [1000], где один параметр времени компиляции будет контролировать, сколько переменных и случайных чисел генерируется. Большое спасибо за ваш ответ; Я просто надеюсь, что что-то может быть наложено поверх него для этой дополнительной возможности настройки. - person Dale; 29.06.2011
comment
Что ж, в какой-то момент вам нужно использовать эти переменные в своем коде, а затем вам явно нужно написать эти N чисел ... так в чем смысл? Вам нужен какой-нибудь массив случайных величин? Это то, что вы хотите? - person Karoly Horvath; 29.06.2011