c语言随机生成int64_t类型的数据_C语言中未初始化变量的值是未知的,能当作“随机值”使用吗?...

在C语言程序中,未初始化的局部变量值是未定义(UB,undefined behaviour)的,使用未初始化的变量可能会为程序带来意想不到的错误,这一点看过我文章的读者应该都是清楚的。

1005ccded515abb3cffc9c88955b4461.png

使用未初始化的变量可能会为程序带来意想不到的错误

“未定义”与“随机值”

但是,反过来想一想,“未定义的”也就意味着未初始化的局部变量内部的值是不确定的,那么它能不能被当作“随机值”使用呢?例如下面这段C语言代码:

void updateEffect(){ for(int i=0;i<1000;i++){ int r, g, b; star[i].setColor(r%255,g%255,b%255); bool isVisible; star[i].setVisible(isVisible); }}

程序仅仅把未初始化的局部变量 r, g, b, isVisible 当作随机值使用,并未在其他逻辑中使用,这样做看起来要比调用 rand() 函数产生随机值效率高多了:

void updateEffect(){ for(int i=0;i<1000;i++){ star[i].setColor(rand()%255,rand()%255,rand()%255); star[i].setVisible(rand()%2==0?true:false); }}
b1953b08f6144668afeeee17d6181694.png

未初始化的局部变量能当作“随机值”吗?

真的如此吗?

首先应该明白,计算机语言是绝对不能有歧义的,因此为C语言程序引入“未定义”的行为无疑是有违这一原则的。另外,使用未初始化局部变量作为随机值,不太可能具有理想的数学统计特性。

例如在 x86(_ 64) 架构中,从未初始化的寄存器中确实会读取出不能事先预知的值,但是这样的值并不能当作是“随机值”,因为局部变量的值存储在栈中,未初始化的值其实是栈中对应位置上一次使用者留下的。

所以如果该栈区一直没有被使用过,那么即使未初始化的局部变量也会每次都有相同的值,这显然不符合预期——产生“随机值”。换句话说,希望未初始化的局部变量提供“随机值”实在是不可靠,甚至指望它每次提供不一样的值都需要依靠运气。

e33b8ddf71519113b997fd3f7f72a87b.png

指望它每次提供不一样的值都需要依靠运气

即使在某段C语言代码中,未初始化的局部变量能够每次都提供不同的值,它们的数学统计特性也是不可靠的,我们不能指望它符合某种分布。

与此同时,引入“未定义”的行为到我们的C语言代码中永远是不值得推荐的做法。程序员永远都不该写不安全的代码,引入的例外越少,最终的程序就越容易避免意外错误。

因此,在C语言程序开发中,如果希望得到一个随机数,那么通过 rand() 函数获取就是最好的选择。基本上也不用担心它的效率,因为基于 rand() 函数的随机数生成器只不过是一个乘法运算,一个加法运算和一个模运算而已。

01991ce723c092e9c8a732fd63c853a6.png

通过 rand() 函数获取随机数就是最好的选择

我所知道的最快的生成器是使用 uint32_t 类型作为随机变量,并且通过下面这个表达式计算:

I = 1664525 * I + 1013904223;

I 的初始值即为所谓的随机数种子,这个表达式可以产生连续的随机数。为了尽量得到高效率的随机数生成器,内联函数和函数式宏定义都是不错的选择。

上面表达式里的两个常数,是由著名的科学程序员 Donald Knuth 手工挑选的。

小结

事实上,随机性是程序开发中非常具体,又非常难以获得的属性。把一些难以追踪的(未定义)数值当作随机值,是一种常见的错误。

8c3fe15fa3e3e5f228d84b739859c3a8.png

点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

未经许可,禁止转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值