18

I would like to generate a random number or string using the C Preprocessor ... um ... I don't even know if this is possible, but I am trying to create variables on the fly (strings would be helpful here) and assign them values (integers). So there are a few things I am trying to do but the basic question remains - can I create a random string or number using the preprocessor.

4
  • 1
    In short: no. You will have to write a simple preprocessor of your own. Don't forget to design a way test your random source code. Commented Mar 18, 2011 at 16:59
  • 1
    Have you seen this? ciphersbyritter.com/NEWS4/RANDC.HTM 1999-01-15 Jeff Stout Commented Mar 18, 2011 at 17:01
  • 6
    Do you really need random or do you just need unique ? If the latter then maybe use __LINE__ to create unique variable names ? Commented Mar 18, 2011 at 17:29
  • 1
    I think Paul identified what the OP really wants to do. Commented Mar 18, 2011 at 17:38

2 Answers 2

23

Based on 1999-01-15 Jeff Stout (thanks to @rlb.usa)

#define UL unsigned long
#define znew  ((z=36969*(z&65535)+(z>>16))<<16)
#define wnew  ((w=18000*(w&65535)+(w>>16))&65535)
#define MWC   (znew+wnew)
#define SHR3  (jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5))
#define CONG  (jcong=69069*jcong+1234567)
#define KISS  ((MWC^CONG)+SHR3)
/*  Global static variables: 
    (the seed changes on every minute) */
static UL z=362436069*(int)__TIMESTAMP__, w=521288629*(int)__TIMESTAMP__, \
   jsr=123456789*(int)__TIMESTAMP__, jcong=380116160*(int)__TIMESTAMP__;


int main(int argc, _TCHAR* argv[]){
    cout<<KISS<<endl;
    cout<<KISS<<endl;
    cout<<KISS<<endl;
}

Output:

247524236
3009541994
1129205949
Sign up to request clarification or add additional context in comments.

6 Comments

Very good implementation for an embedded system. Both answers are good.
What does it mean: "the seed changes on every minute"? What event changes it?
@user10133158 __TIMESTAMP__ is a compiler variable that has a 1-minute precision. So, every different minute you compile, the seed changes
This is misleading because it does not use the preprocessor to compute a random number, as OP requested. Instead it inserts a block of C code that will be compiled into code that computes a number.
@nergeia Nonsense. Run it with gcc -E (preproccesor only) to see the result: cout<<(((((z=36969*(z&65535)+(z>>16))<<16)+((w=18000*(w&65535)+(w>>16))&65535))^(jcong=69069*jcong+1234567))+(jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5)))<<endl;
|
16

I take your question that you want to have a way of creating unique identifier tokens through the preprocessor.

gcc has an extension that is called __COUNTER__ and does what you expect from its name. You can combine this with macro concatenation ## to obtain unique identifiers.

If you have a C99 compiler you can use P99. It has macros called P99_LINEID and P99_FILEID. They can be used as

#include "p99_id.h"

P99_LINEID(some, other, tokens, to, make, it, unique, on, the, line)

and similarily for P99_FILEID.

The first mangles a name from your tokens and the line number and a hash that depends on the number of times the file "p99_id.h" had been included. The second macro just uses that hash and not the line number such that a name is reproducible at several places inside the same compilation unit.

These two macros also have counterparts P99_LINENO and P99_FILENO that just produce large numbers instead of identifier tokens.

2 Comments

Wanted to add that __COUNTER__ is also available for other compilers like MSVC. Just be aware that __COUTER__ is only unique for the file the pre-processor is currently parsing (it starts with 0 for each source file parsed).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.