2012-05-21 5 views
5

Возможно ли это?Возможно инициализировать статическую переменную вызывающей функцией

static bool initialize() 
{ 
    TRC_SCOPE_INIT(...); 
    ... 
} 

static bool initialized = initialize(); 

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

+1

Можете ли вы вставить вызов 'pthread_once (3)' в свою 'main()' подпрограмму? – sarnold

+0

@KingsIndian: 'bool' действителен в C99 с заголовком' stdbool.h'. – icktoofay

+0

@icktoofay В любом случае он не был указан как c99, поэтому добавлен тег C++. –

ответ

6

Когда я первоначально посмотрел на вопрос, он был помечен как C, так и C++. Код может быть C или C++, потому что bool является типом в C99 и C11, так же, как и на C++ (почти на C, для получения имени bool нужен заголовок <stdbool.h>).

Ответы на двух тегов:

  • В C++, да.

  • В С, №.

Это не тот же язык. Если вам нужна демонстрация, это также хороший пример, как любой.

+2

Вопрос был отмечен только 'c', когда он был первоначально опубликован. @KingsIndian добавил тег 'C++' из-за 'bool', но я вернул это редактирование, потому что' bool' действительно на C99, и из исходного сообщения не было указаний о том, что он был связан с C++. – icktoofay

+0

@icktoofay: спасибо за разъяснение; Я немного скорректировал свой ответ, чтобы узнать об изменениях. –

+0

для тех, кому интересно, (a) C++ 11 позволяет использовать constexpr, (b) существует удивительно небольшая поддержка компилятора для него –

1

Это должно быть в порядке, если инициализация «вещи», которую вы инициализируете, определяется в той же единице перевода, что и вызов функции, которая ее инициализирует. Кроме того, он должен быть определен над сайтом вызова. В противном случае вы рискуете неопределенным поведением из-за использования неинициализированных значений.

Один из способов обойти это - вместо этого использовать указатель. Статически инициализированный указатель компилируется в исполняемый образ, поэтому нет риска неопределенного поведения, если он используется статикой, определенной в других единицах перевода. В вашей статической функции инициализации вы динамически выделяете «материал» и устанавливаете указатель на него, чтобы вы могли получить к нему доступ позже.

4

Если вы используете GCC (или лязг), вы можете использовать __attribute__((constructor)):

static bool initialized = false; 

__attribute__((constructor)) 
static void initialize(void) { 
    initialized = true; 
    // do some other initialization 
} 

int main(int argc, char **argv) { 
    // initialize will have been run before main started 
    return 0; 
} 
1

(Поскольку вы упомянули темы, я буду считать, что у вас есть функции потоков POSIX в вашем распоряжении.)

Функция pthread_once существует для этой цели. Везде вы должны быть уверены, что initialize уже назвали, пишут:

pthread_once(&init_once, initialize); 

где init_once определяется со статической продолжительностью хранения, и, возможно, с внешним связыванием в случае необходимости, в качестве pthread_once_t init_once.

Смежные вопросы