有没有一个函数生成一个随机int数在C?或者我必须使用第三方库?


当前回答

FWIW,答案是肯定的,有一个stdlib.h函数叫rand;此函数主要针对速度和分布进行调优,而不是针对不可预测性。几乎所有语言和框架的内置随机函数都默认使用这个函数。还有“加密”随机数生成器,它们的可预测性要低得多,但运行速度要慢得多。在任何类型的与安全相关的应用程序中都应该使用它们。

其他回答

您可以使用悬浮指针的概念。

指向已删除(或释放)内存位置的指针称为悬浮指针。

它将在打印时显示随机值。

与此相关的特定于glibc的函数(应该在大多数Linux环境中都可以找到)是random(),或者您可能对其线程安全版本random_r()感兴趣。在将结构体random_data传递给random_r()之前,必须使用initstate_r()初始化它。

下面是一个快速的代码示例:

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

void xxx (void) {
    unsigned int seed = (unsigned int) time(NULL);
    char rnd_state[17] = {0};
    struct random_data rnd_st_buf = {0};
    initstate_r(seed, &rnd_state[0], 17, &rnd_st_buf);
    for(size_t idx = 0; idx < 8; idx++) {
        int32_t rnd_int = 0;
        char rnd_seq_str[6] = {0};
        random_r(&rnd_st_buf, &rnd_int);
        memcpy((char *)&rnd_seq_str[0], (char *)&rnd_int, 4);
        printf("random number : 0x%08x,  \n", rnd_int);
    }
}

在现代的x86_64 cpu上,您可以通过_rdrand64_step()使用硬件随机数生成器。

示例代码:

#include <immintrin.h>

uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
  // Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number

<stdlib.h>中的rand()函数返回一个介于0和RAND_MAX之间的伪随机整数。你可以使用srand(unsigned int seed)来设置种子。

通常的做法是将%操作符与rand()结合使用以获得不同的范围(但请记住,这在一定程度上破坏了一致性)。例如:

/* random int between 0 and 19 */
int r = rand() % 20;

如果你真的在乎一致性,你可以这样做:

/* Returns an integer in the range [0, n).
 *
 * Uses rand(), and so is affected-by/affects the same seed.
 */
int randint(int n) {
  if ((n - 1) == RAND_MAX) {
    return rand();
  } else {
    // Supporting larger values for n would requires an even more
    // elaborate implementation that combines multiple calls to rand()
    assert (n <= RAND_MAX)

    // Chop off all of the values that would cause skew...
    int end = RAND_MAX / n; // truncate skew
    assert (end > 0);
    end *= n;

    // ... and ignore results from rand() that fall above that limit.
    // (Worst case the loop condition should succeed 50% of the time,
    // so we can expect to bail out of this loop pretty quickly.)
    int r;
    while ((r = rand()) >= end);

    return r % n;
  }
}

对于Linux C应用程序:

这是我根据上面的答案重新编写的代码,它遵循我的C代码实践并返回任意大小的随机缓冲区(具有适当的返回代码等)。确保在程序开始时调用urandom_open()一次。

int gUrandomFd = -1;

int urandom_open(void)
{
    if (gUrandomFd == -1) {
        gUrandomFd = open("/dev/urandom", O_RDONLY);
    }

    if (gUrandomFd == -1) {
        fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
                  errno, strerror(errno));
        return -1;
    } else {
        return 0;
    }
}


void urandom_close(void)
{
    close(gUrandomFd);
    gUrandomFd = -1;
}


//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
    int ret = 0; // Return value

    if (gUrandomFd == -1) {
        fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
        return -1;
    }

    ret = read(gUrandomFd, buf, size);

    if (ret != size) {
        fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
                 ret, size);
        return -1;
    } else {
        return 0;
    }
}