`
hanyezhiyu8
  • 浏览: 153645 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

[MFC] rand_s 的用法

阅读更多

大家都知道如何用 C++ <stdlib.h> 中的 rand 配合随机数种子来生成伪随机数。本文介绍另一种不需要每次通过系统时间来设置伪随机序列起始位置的方法(仅仅针对 Window XP 以及之后的操作系统),那就是使用同样在 <stdlib.h> 中的 rand_s 函数。

有的人说,一看这个函数的名字就知道了,不就是带 CRT 安全增强版的 rand 函数嘛!的确,这个函数是附带 CRT 安全增强的,不过和其它带 CRT 安全增强的函数有所不同——即便你在程序中仍然使用 rand ,编译器也不会有安全警告,因为在 XP 之前的操作系统只能用 rand() 函数。这主要是因为 rand_s 使用的是操作系统来生成加密安全的伪随机数,而不是像 rand 那样使用 srand 生成的种子。所以,使用 rand_s 生成随机数的话就不需要每次都去调用 srand 了。

现在来看看这个函数的声明:
  errno_t rand_s( unsigned int* randomValue );

函数的参数是一个整型的指针,指向一个用于接收随机数的整数类型。啥?为啥不直接返回随机数?我个人的猜测是因为 rand_s 直接把这个指针传递给了操作系统用于生成随机数的 API 函数 RtlGenRandom (大家知道 API 函数都是用缓冲区来接收数据),算是写代码的人偷了一个懒吧!
函数成功的话,返回值是 0;否则的话返回错误代码。
生成的随机数范围是 0-UINT_MAX。
而最重要的是:
如果想使用这个函数,必须在 <stdlib.h> 这个头文件被包含之前定义一个宏:_CRT_RAND_S,也就是如下:

#define _CRT_RAND_S
#include <stdio.h>

如果没有这样做,在编译的时候就会提示找不到 rand_s 这个标识符!
这也就衍生了一个比较容易被忽略的问题,而这个问题在 MSDN 中并没有提示——
如果你的程序包含了一个“包含 <stdlib.h> 的头文件”,那么即便你在之后写上面那两行也是没用的,因为在宏被定义前 <stdlib.h> 就已经被包含了。这个问题最有可能在使用了预编译头的 MFC 程序中出现——很多人没有意识到 MFC 的那两个头文件(<afxwin.h>、<afxext.h>)已经包含了 <stdlib.h>,所以在预编译头后面写上这两句是没有作用的。正确的做法应该是在 MFC 的头文件被包含之前(预编译头中)定义 _CRT_RAND_S 这个宏。
下面就用这个函数来实现一个在 min-max 范围中(不包括 max)生成随机数的过程:


unsigned randInt(int min, int max)
{
    unsigned u;
    rand_s(&u);
    return (unsigned)((double)u / ((__int64)UINT_MAX + 1) * (max - min) + min);
}

基本上和以前用 rand 的算法相同,只不过这次 rand_s 生成的数上限是 32 位整数的最大值,想要 + 1 的话只能使用 62 位整数。

 

以上来自:http://kevin-hust.iteye.com/blog/744284

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics