Это хорошая идея, чтобы передать переменную без инициализации srand?


Является ли хорошей идеей передать неинициализированную переменную в srand вместо результата time(NULL)?
Это на один #include и один вызов функции меньше.

Пример кода:

#include <stdlib.h>

int main(void) {
    {
        usigned seed; //uninitialized
        srand(seed);
    }
    //other code
    return 0;
}

Вместо

#include <stdlib.h>
#include <time.h>

int main(void) {
    srand(time(NULL));
    //other code
    return 0;
}
5 3

5 ответов:

Нет, это не так.

Чтение неинициализированного значения приводит к неопределенному поведению. Она может быть нулевой, может быть полуслучайной-но как таковая, она может многократно повторять одно и то же значение. Это также может привести к ошибкам компиляции или времени выполнения, или сделать любую другую совершенно непредсказуемую вещь.

Затем кто-то другой, компилирующий вашу программу, заметит предупреждение компилятора о неинициализированном значении и попытается исправить его. Он может исправить это правильно, или, учитывая достаточно сложную программу, он может просто инициализировать ее, чтобы ноль. Вот как "маленькие" ошибки превращаются в огромные ошибки.


Просто попробуйте ваш фрагмент с srand() заменен на printf():

#include <stdio.h>

int main()
{
    {
        unsigned seed;
        printf("%u\n", seed);
    }

    return 0;
}

По моей системе он неоднократно дает 0. Это означает, что существует по крайней мере одна система, в которой ваш код нарушен :).

Нет, обращение к неинициализированной переменной-это неопределенное поведение. Вы должны предпочесть time(NULL). Неинициализированный метод переменных может ввести трудные для поиска ошибки или может взорвать компьютер.

Большую часть времени наблюдаемый эффект будет заключаться в том, что (на большинстве реализаций) вышеописанный код будет принимать (читать) некоторое остаточное значение из стека, которое может быть нулевым или чем-то еще, но может быть одинаковым при нескольких запусках, разрушающих вашу цель. time с другой стороны, это многообещающе.

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

Другой момент заключается в том, что неинициализированные переменные могут привести к уязвимости . Так что это не только плохой дизайн и неопределенное поведение, это также может сделать вашу программу эксплуатируемой.

Рассмотрим этот код :

#include <stdio.h>
#include <time.h>

void print_uninitialized(void) {
    unsigned var;
    printf("%u\n", var);
}

void fake_init() {
    unsigned var=42;
}

int main(void) {
    print_uninitialized();
    fake_init();
    print_uninitialized();
}

Возможный выход:

0
42

Следующий пример немного более реалистичен:

#include <stdio.h>

unsigned uninitialized( void ) {
    unsigned var;
    return var;
}

unsigned square(unsigned arg){
    unsigned result=arg*arg;
    return result;
}

int main( void ) {
    unsigned to_square;
    printf("UNINITIALIZED = %u\n", uninitialized());
    while(scanf("%u", &to_square)!=EOF){
        printf("%u * %u = %u\n", to_square, to_square, square(to_square));
        printf("UNITNITIALIZED = %u\n", uninitialized());
    }
}
Неинициализированная переменная может быть изменена пользователем.

Вход:

2

Вывод:

UNINITIALIZED = 0
2 * 2 = 4
UNITNITIALIZED = 4

В первом случае возможны два варианта:

  • семя-это случайная величина (менее возможная)
  • семя постоянно на каждом прогоне (более возможно)

Time (NULL) возвращает время системы, которое на 99,99% отличается при каждом запуске кода.

Ничто не является совершенной случайностью, но использование времени(NULL) дает вам "более случайное" число, чем если бы вы использовали первый подход.

Вы должны проверить функцию использование http://www.cplusplus.com/reference/cstdlib/srand/