【问题标题】:Is it good idea to pass uninitialized variable to srand?将未初始化的变量传递给 srand 是个好主意吗?
【发布时间】:2014-11-12 08:07:21
【问题描述】:

将未初始化的变量传递给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;
}

【问题讨论】:

  • 您为什么认为任何使用未初始化的变量是个好主意?
  • 初始化并不意味着随机。只需使用时间(NULL)。
  • 除非你想在每次运行程序时都生成同一系列的随机数,否则我认为这不是一个好主意。
  • 未定义行为意味着任何事情都可能发生。程序可能会崩溃。它可能看起来工作正常。根据月相,它可能会默默地破坏记忆。它可能会擦除您的硬盘驱动器。它可能会向您的母亲发送一封令人讨厌的电子邮件。它可能会让恶魔从你的鼻子里飞出来。就 C 语言而言,存在所有允许的行为。

标签: c++ c srand


【解决方案1】:

不,不是。

读取未初始化的值会导致未定义的行为。它可以是零,也可以是半随机的——但同样地,它可以重复为相同的值。它还可能导致编译或运行时错误,或做任何其他完全不可预测的事情。

然后,编译您的程序的其他人会注意到编译器警告有关未初始化值并尝试修复它。他可能会正确修复它,或者给定足够复杂的程序,他可能会将其初始化为零。 'small' bugs turn into huge bugs就是这样。


只需将srand() 替换为printf() 试试你的sn-p:

#include <stdio.h>

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

    return 0;
}

在我的系统上它反复给出0。这意味着您的代码至少有一个系统被破坏:)。

【讨论】:

  • 你从未定义的行为继续......“它可以是零,它可以是半随机的......”,但这会分散注意力的重点 - 它可能会崩溃或破坏程序行为 - 所有赌注都被取消,而不仅仅是 seed 的初始值。
【解决方案2】:

不,访问未初始化的变量是未定义的行为。你应该更喜欢time(NULL)。未初始化的变量方法可能会引入难以发现的错误或可能会损坏计算机。

大多数情况下,观察到的效果是,(在大多数实现中)上面的代码会从堆栈中获取(读取)一些剩余值,这些值可能为零或其他值,但在多次运行时可能相同,从而破坏了您的目的。另一方面,time 很有希望。

【讨论】:

  • " ...否则可能会炸毁计算机" 认真的吗?
  • @RogerRowland 我的一位戏剧女王老师曾经用这种方式夸大了 UB。关键是,不要这样做。始终编​​写具有明确行为的代码。
【解决方案3】:

这不是一个好主意。未定义的行为并不能保证每次运行都不会获得相同的种子,这对随机性不利。它也不能保证您的处理器也不会停止并着火。

【讨论】:

  • 这是未定义的行为,因此没有任何保证。
  • 好的,我现在已经更明确了。
【解决方案4】:

另一点是未初始化的变量可能导致vulnerability。因此,这不仅是糟糕的设计和未定义的行为,它还可能使您的程序可被利用

考虑this code

#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

The next example 更现实一点:

#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

【讨论】:

【解决方案5】:

第一种情况有两种可能:

  • 种子是随机变量(不太可能)
  • 每次运行时种子都是不变的(更有可能)

time(NULL) 每次运行代码时返回的系统时间相差 99.99%。

没有什么是完全随机的,但是如果你使用第一种方法,那么使用 time(NULL) 会给你一个“更随机”的数字。

你应该检查函数的使用情况 http://www.cplusplus.com/reference/cstdlib/srand/

【讨论】:

  • 请注意,SO 上的 C++ 社区通常更喜欢 cppreference 而不是 cplusplus.com
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 2022-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多