Static Variable Must Be Constant?

  • Thread starter Michael B Allen
  • Start date
M

Michael B Allen

I want to initialize a static variable to a "random" value like:

static void *
get_key(struct dnsreq *req)
{
static uint16_t next_txnid = (uint32_t)req & 0xFFFF;

But gcc gives me an error:

src/dns.c: In function `get_key':
src/dns.c:173: initializer element is not constant

So a static initializer must be a constant?

Must I do:

static uint16_t next_txnid = 0;

if (!next_txnid) {
(uint32_t)req & 0xFFFF;
}

?

Thanks,
Mike
 
K

Kenneth Bull

Michael said:
I want to initialize a static variable to a "random" value like:

static void *
get_key(struct dnsreq *req)
{
static uint16_t next_txnid = (uint32_t)req & 0xFFFF;

You can't INITIALIZE a static variable with an expression that isn't a
constant expression. But you are free to ASSIGN to a static variable
with a variable or constant expression.

do this:

static uint16_t next_txnid; /* compiler will initialize to zero */
next_txnid = (uint32_t)req & 0xFFFF; /* you assign something to it */


INITALIZATIONS are for STARTING VALUES. Since static variables START
before a program begins, the initial values for static variables must
not depend on variables (like req) whose values can't be determined
before program start. Thus, your compiler needs to know what your
static variable's value will be before program start, which obviously
can't be a variable expression. In your case, does it matter what the
value of next_txnid is at program start? Most likely no.
 
P

Peter Nilsson

Michael said:
I want to initialize a static variable to a "random" value like:

static void *
get_key(struct dnsreq *req)
{
static uint16_t next_txnid = (uint32_t)req & 0xFFFF;

But gcc gives me an error:

src/dns.c: In function `get_key':
src/dns.c:173: initializer element is not constant

So a static initializer must be a constant?

Yes.

But the question is, since you overwrite the value immediately
on each function call entry, why do you need the variable to
have static duration in the first place?

If you're just trying to save stack allocation overhead for
a specific implementation, then just do...

static uint16_t next_txnid;
next_txnid = req & 0xFFFFu;
 
D

Dmitry

Michael said:
So a static initializer must be a constant?

Of course, initializers are computed during compile time
Must I do:

static uint16_t next_txnid = 0;

if (!next_txnid) {
(uint32_t)req & 0xFFFF;
}

Just separate declaration and assignment:

static uint16_t next_txnid;
next_txnid = (uint32_t)req & 0xFFFF;
 
M

Michael B Allen

INITALIZATIONS are for STARTING VALUES. Since static variables START
before a program begins, the initial values for static variables must
not depend on variables

Good explaination. Thanks.

Mike
 
L

Lawrence Kirby

I want to initialize a static variable to a "random" value like:

static void *
get_key(struct dnsreq *req)
{
static uint16_t next_txnid = (uint32_t)req & 0xFFFF;

But gcc gives me an error:

src/dns.c: In function `get_key':
src/dns.c:173: initializer element is not constant

So a static initializer must be a constant?

Yes, static variables are initialised once at program startup. So in your
example code next_txnid would *not* be initialised when the function is
called, only at program startup when the variable req doesn't exist.
Must I do:

static uint16_t next_txnid = 0;

if (!next_txnid) {
(uint32_t)req & 0xFFFF;

I assume you mean

next_txnid = (uint32_t)req & 0xFFFF;

So it appears that you want the one-off initialisation behaviour but at
the first time get_key() is called. If so then, yes, this is a reasonable
approach assuming of course that (uint32_t)req & 0xFFFF can't be zero. A
more exact approach would use a separate flag variable indicating whether
next_txnid had been initialised or not.

Lawrence
 
A

Andrey Tarasevich

Michael said:
...
So a static initializer must be a constant?
Yes.

Must I do:

static uint16_t next_txnid = 0;

if (!next_txnid) {
(uint32_t)req & 0xFFFF;

Did you mean
next_txnid = (uint32_t)req & 0xFFFF;

Yes, that's one way to do it, provided '0' is not one of the possible
results of '(uint32_t)req & 0xFFFF'. If it is, you might end up with
"initializations" that don't register a such, i.e. the variable will be
"re-initialized" again every time you go through this code.

Otherwise, if there's no definitive reserved "impossible" value among
the results of '(uint32_t)req & 0xFFFF' expression, you'll have no other
choice but to create another variable just to serve as a boolean
"already initialized" flag.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,233
Latest member
AlyssaCrai

Latest Threads

Top