2012-05-21 41 views
5

Điều này có khả thi không?Có thể khởi tạo biến tĩnh bằng cách gọi hàm

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

static bool initialized = initialize(); 

Để thực hiện một câu chuyện rất dài ngắn, tôi cần phải gọi một loạt các macro (để khởi gỡ lỗi thông điệp) càng sớm càng tốt (trước khi chủ đề X được bắt đầu, và tôi không có khả năng biết khi chuỗi X được bắt đầu).

+1

Bạn có thể chèn một cuộc gọi đến 'pthread_once (3)' trong thường trình 'main()' không? – sarnold

+0

@KingsIndian: 'bool' là hợp lệ trong C99 với tiêu đề' stdbool.h'. – icktoofay

+0

@icktoofay Nó chưa được chỉ định là c99, vì vậy thêm C++ tag. –

Trả lời

6

Khi tôi xem xét câu hỏi ban đầu, nó đã được gắn thẻ cả C và C++. Mã có thể là C hoặc C++ vì bool là một loại trong C99 và C11, giống như trong C++ (gần như trong C, bạn cần tiêu đề <stdbool.h> để có được tên bool).

Những câu trả lời cho hai thẻ là:

  • Trong C++, vâng.

  • Trong C, không.

Chúng không giống ngôn ngữ. Nếu bạn cần một cuộc biểu tình, đây là một ví dụ tốt như bất kỳ.

+2

Câu hỏi đã được gắn thẻ chỉ 'c' khi nó được đăng lần đầu. @KingsIndian đã thêm thẻ 'C++' vì' bool', nhưng tôi đã hoàn nguyên chỉnh sửa đó vì 'bool' là hợp lệ trong C99 và không có dấu hiệu nào từ bài gốc mà nó có liên quan đến C++. – icktoofay

+0

@icktoofay: cảm ơn bạn đã làm rõ; Tôi đã điều chỉnh câu trả lời của mình một chút để nhận ra những thay đổi. –

+0

cho những người tò mò, (a) C++ 11 cho phép bạn sử dụng constexpr, (b) có ít hỗ trợ trình biên dịch đáng ngạc nhiên cho nó –

1

Điều này sẽ ổn khi cung cấp "nội dung" bạn đang khởi tạo được xác định trong cùng đơn vị dịch như cuộc gọi đến chức năng khởi tạo nó. Ngoài ra, nó phải được xác định trên trang web cuộc gọi. Nếu không, bạn có nguy cơ hành vi không xác định do sử dụng các giá trị uninitialized.

Một cách để giải quyết vấn đề này là sử dụng con trỏ để thay thế. Một con trỏ được khởi tạo tĩnh được biên dịch thành hình ảnh thực thi, do đó không có nguy cơ về hành vi không xác định nếu nó được sử dụng bởi các số liệu thống kê được xác định trong các đơn vị dịch thuật khác. Trong hàm khởi tạo tĩnh của bạn, bạn tự động phân bổ "công cụ" và đặt con trỏ trỏ đến nó để bạn có thể truy cập nó sau này.

4

Nếu bạn đang sử dụng GCC (hoặc kêu vang), bạn có thể sử dụng __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

(Kể từ khi bạn đề cập đến chủ đề, tôi sẽ giả sử bạn có chức năng chủ đề POSIX theo ý của bạn.)

Chức năng pthread_once tồn tại cho mục đích chính xác này. Bất cứ nơi nào bạn cần phải chắc chắn initialize đã được gọi, viết:

pthread_once(&init_once, initialize); 

nơi init_once được định nghĩa với thời gian lưu trữ tĩnh, và có thể có mối liên hệ bên ngoài nếu cần thiết, như pthread_once_t init_once.

Các vấn đề liên quan