How to generate a random int in C?

后端 未结 27 2481
故里飘歌
故里飘歌 2020-11-22 00:31

Is there a function to generate a random int number in C? Or will I have to use a third party library?

27条回答
  •  梦如初夏
    2020-11-22 00:40

    If your system supports the arc4random family of functions I would recommend using those instead the standard rand function.

    The arc4random family includes:

    uint32_t arc4random(void)
    void arc4random_buf(void *buf, size_t bytes)
    uint32_t arc4random_uniform(uint32_t limit)
    void arc4random_stir(void)
    void arc4random_addrandom(unsigned char *dat, int datlen)
    

    arc4random returns a random 32-bit unsigned integer.

    arc4random_buf puts random content in it's parameter buf : void *. The amount of content is determined by the bytes : size_t parameter.

    arc4random_uniform returns a random 32-bit unsigned integer which follows the rule: 0 <= arc4random_uniform(limit) < limit, where limit is also an unsigned 32-bit integer.

    arc4random_stir reads data from /dev/urandom and passes the data to arc4random_addrandom to additionally randomize it's internal random number pool.

    arc4random_addrandom is used by arc4random_stir to populate it's internal random number pool according to the data passed to it.

    If you do not have these functions, but you are on Unix, then you can use this code:

    /* This is C, not C++ */
    #include 
    #include 
    #include 
    #include 
    #include 
    #include  /* exit */
    #include  /* printf */
    
    int urandom_fd = -2;
    
    void urandom_init() {
      urandom_fd = open("/dev/urandom", O_RDONLY);
    
      if (urandom_fd == -1) {
        int errsv = urandom_fd;
        printf("Error opening [/dev/urandom]: %i\n", errsv);
        exit(1);
      }
    }
    
    unsigned long urandom() {
      unsigned long buf_impl;
      unsigned long *buf = &buf_impl;
    
      if (urandom_fd == -2) {
        urandom_init();
      }
    
      /* Read sizeof(long) bytes (usually 8) into *buf, which points to buf_impl */
      read(urandom_fd, buf, sizeof(long));
      return buf_impl;
    }
    

    The urandom_init function opens the /dev/urandom device, and puts the file descriptor in urandom_fd.

    The urandom function is basically the same as a call to rand, except more secure, and it returns a long (easily changeable).

    However, /dev/urandom can be a little slow, so it is recommended that you use it as a seed for a different random number generator.

    If your system does not have a /dev/urandom, but does have a /dev/random or similar file, then you can simply change the path passed to open in urandom_init. The calls and APIs used in urandom_init and urandom are (I believe) POSIX-compliant, and as such, should work on most, if not all POSIX compliant systems.

    Notes: A read from /dev/urandom will NOT block if there is insufficient entropy available, so values generated under such circumstances may be cryptographically insecure. If you are worried about that, then use /dev/random, which will always block if there is insufficient entropy.

    If you are on another system(i.e. Windows), then use rand or some internal Windows specific platform-dependent non-portable API.

    Wrapper function for urandom, rand, or arc4random calls:

    #define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
    
    int myRandom(int bottom, int top){
        return (RAND_IMPL() % (top - bottom)) + bottom;
    }
    

提交回复
热议问题