2014-02-13 12 views
4

Я пытаюсь инициализировать переменную const с глобальным охватом со значением, которое соответствующим образом заменяется байтом.Инициализация переменной const с помощью ntohl()

#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; 
} 

Использование gcc не работает с «error: initializer element is not constant». Да, хорошо, поэтому заголовок gcc имеет ntohl(), определенный как функция, или как «do {...} while (0)» или что-то подобное, которое невозможно оценить во время компиляции. Облом.

Есть ли что-нибудь, что я могу сделать, который достигнет того же конца? Мне нужно инициализировать значение для соответствующей конечности, и я хочу, чтобы это была глобальная область. Есть ли способ убедить gcc сделать это, за исключением качки моего собственного ntohl-подобного макроса?

(Кстати, замечу, что лязг имеет ntohl() определяется таким образом, что оно может быть вычислено во время компиляции. Приведенный выше пример кода отлично работает с лязгом. К сожалению, я не получаю мой выбор составителей.)

ответ

2

Инициализировать его в main() или использовать что-то вроде (предполагается, что Linux):

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

или, возможно,

#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 
3

Раздел 6.7.8/4 стандарта читает

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

Вызов ntohl не является ни постоянным выражением, ни строковым. Вы не можете добраться туда отсюда.

Но глобальные переменные в любом случае плохи, и я подозреваю, что это может быть преждевременная оптимизация. Легкое исправление заключается в том, чтобы использовать выражение непосредственно в вашем коде, которое не будет иметь никакого эффекта вообще на платформах большого конца, , например.,

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

Еще лучше, если использовать макрос препроцессора, как в

#define POTRZEBIE ntohl(0x11223344) 

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

В переменных с автоматическим хранением, const классификатора означает одно назначения, так что нет никаких проблем с выше использованием.