Domanda

I'm trying to initialize a global-scoped const variable with a value that is byte-swapped appropriately.

#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>

const uint32_t a = ntohl(0x11223344);

int main(int argc, char const *argv[])
{
    printf("%08x\n", a);
    return 0;
}

Using gcc this fails with "error: initializer element is not constant". Yeah, okay, so the gcc header has ntohl() defined as a function or as "do {...} while (0)" or something similar that can't be evaluated at compile time. Bummer.

Is there anything I can do which will achieve the same end? I need to initialize the value for the appropriate endedness, and I want it to be a globally-scoped const. Is there any way to convince gcc to do this, short of rolling my own ntohl-like macro?

(BTW, I note that clang has ntohl() defined such that it can be evaluated at compile time. The above code sample works perfectly with clang. Unfortunately I don't get my pick of compilers.)

È stato utile?

Soluzione 2

Initialize it in main() or use something like (assuming Linux):

 #include <endian.h>
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 const uint32_t a = 0x44332211;
 #else
 const uint32_t a = 0x11223344;
 #endif

or perhaps

 #include <endian.h>
 #define A_ADDR 0x11223344
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 const uint32_t a = __bswap_constant_32(A_ADDR);
 #else
 const uint32_t a = A_ADDR;
 #endif

Altri suggerimenti

Section 6.7.8/4 of the standard reads

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

A call to ntohl is neither a constant expression nor a string literal. You can’t get there from here.

But global variables are bad anyway, and I suspect this may be a premature optimization. The easy fix is to use the expression directly in your code, which will have no effect at all on big-endian platforms, e.g.,

void foo(void)
{
  const unit32_t a = ntohl(0x11223344);
  /* ... */
}

Even better, use a preprocessor macro, as in

#define POTRZEBIE ntohl(0x11223344)

void bar(void)
{
  const unit32_t a = POTRZEBIE;
  /* ... */
}

On variables with automatic storage, the const qualifier means single assignment, so there is no problem with the above usage.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top