Это хорошая идея, чтобы передать переменную без инициализации 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 ответов:
Нет, это не так.
Чтение неинициализированного значения приводит к неопределенному поведению. Она может быть нулевой, может быть полуслучайной-но как таковая, она может многократно повторять одно и то же значение. Это также может привести к ошибкам компиляции или времени выполнения, или сделать любую другую совершенно непредсказуемую вещь.Затем кто-то другой, компилирующий вашу программу, заметит предупреждение компилятора о неинициализированном значении и попытается исправить его. Он может исправить это правильно, или, учитывая достаточно сложную программу, он может просто инициализировать ее, чтобы ноль. Вот как "маленькие" ошибки превращаются в огромные ошибки.
Просто попробуйте ваш фрагмент с
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/