Testing For the random() Function

Silly me. I once assumed that just because my compiler offered the random() function — a superior version of the C library standard rand() function — that every compiler fatured this function. Boy, was I wrong!

The random() function improves upon the randomness of rand() using technical mumbo jumbo that I don’t want to understand. It also features a companion, srandom() function to seed its randomizer. All I know is that these functions are better than rand() and srand(). But I also learned is that not every compiler offers these POSIX/BSD functions.

To write the best code, you should check for compatibility before implementing a POSIX or BSD function like random(). The test parameters are listed in the function’s man page documentation:

CONFORMING TO      POSIX.1-2001, POSIX.1-2008, 4.3BSD.

The POSIX defined constant to test is named _POSIX_C_SOURCE. This value must be greater than or equal to 200112L (long int) to ensure that the relevant function is available as documented.

The following code tests the POSIX version, confirming whether the random() function is available.

2024_11_02-Lesson-a.c

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

#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 0
#endif

int main()
{
    /* test for presence of random() function */

    if( _POSIX_C_SOURCE >= 200112L )
        puts("The random() function is available");
    else
        puts("The random() function is not available");

    return 0;
}

Before the main() function, the precompiler tests for the presence of the _POSIX_C_SOURCE defined constant. If the constant is undefined, the code defines it. This test ensures that the code compiles, otherwise an error occurs should the defined constant be undefined.

Within the main() function, the value of _POSIX_C_SOURCE is compared with 200112L. When true (the value is greater than or equal to), the output shows that the random() function is available.

Here’s a sample run:

The random() function is available

If I compile the code with the -ansi switch, setting it to conform with the original ANSI C standard, I see this result:

The random() function is not available

This is the output a user sees when the compiler doesn’t use the POSIX C extensions.

The following code is more practical, showing how to implement the test:

2024_11_02-Lesson-b.c

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

int main()
{
    int x;

#ifdef _POSIX_C_SOURCE
    if( _POSIX_C_SOURCE >= 200112L )
    {
        srandom( (unsigned)time(NULL) );
        puts("The random() function:");
        for( x=0; x<10; x++ )
            printf("%ld\n",random());
    }
    else
    {
        srand( (unsigned)time(NULL) );
        puts("The rand() function:");
        for( x=0; x<10; x++ )
            printf("%d\n",rand());
    }
#else
    srand( (unsigned)time(NULL) );
    puts("The rand() function:");
    for( x=0; x<10; x++ )
        printf("%d\n",rand());
#endif

    return 0;
}

With this example, the precompiler directives are checked inside the code. When the _POSIX_C_SOURCE constant is defined (#ifdef), a if test ensures that the version is compatible with the random() function:

if( _POSIX_C_SOURCE >= 200112L )

Otherwise, the else part of the code uses the rand() function.

The #else directive handles the case when the _POSIX_C_SOURCE constant is undefined. This part of the code is compiled using only the rand() function.

An #endif directive ends the #ifdef#else construction.

Here is the output:

The random() function:
1650599212
420354732
1514728248
139032251
1888432268
1534300142
157468978
1753183110
1160242387
22997577

When the -ansi switch is used to compile the code, here is the output:

The rand() function:
1512047070
1354075150
158955988
1182828959
332400900
1817095792
1455458813
418963527
1268248241
1994796880

This code is built to handle three situations: When the POSIX standard is compatible with random(), when it’s not, and when the POSIX standard is undefined. Thanks to the precompiler directives, two different programs are generated depending on the presence of the _POSIX_C_SOURCE constant. The program can build on any platform and do its job, even when the random() function is unavailable.

Leave a Reply