2012-08-03 55 views
0

下面的代碼生成錯誤:初始化元素不是常量 在編譯時聲明和初始化用戶結構變量的行。如何將sizeof運算符應用於函數指針並初始化結構?

#include <stdio.h> 
#include <stdlib.h> 

struct user_s { 
    char *name; 
    void (*(*pred_skip_func))(int); 
}; 

void f1 (int skip) { 
    printf("I am f1\n"); 
} 

void f2 (int skip) { 
    printf("I am f2\n"); 
} 

void (*(*pred_skip_func))(int); 
struct user_s user = {"Manu", pred_skip_func}; 

int main(void) { 

    struct user_s tmp; 
    pred_skip_func = malloc(sizeof(tmp.pred_skip_func) * 2); 
    pred_skip_func[0] = f1; 
    pred_skip_func[1] = f2; 

    int i; 
    for (i = 0; i < 2; i++) { 
     (*(user.pred_skip_func)[i]) (i); 
    } 
    return EXIT_SUCCESS; 
} 

在主函數中移動初始化解決了這個問題,但我想明白爲什麼?結構初始化有沒有限制?

更重要的是,您可以看到,我創建了一個tmp user_struc變量來獲取函數指針的指針大小,因爲我無法以更清晰的方式執行此操作。我怎樣才能解決這個問題 ?

回答

2

第一個問題:

「結構初始化有沒有限制?

C需要具有靜態存儲持續時間聚合類型初始化爲常數:

(C99, 6.7.8p4) "All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals."

注意,在C89即使聚合類型的對象具有自動存儲持續時間的intializers必須是常量表達式(這在C99中不再是這種情況)。

第二個問題:

「更多了,因爲你可以看到,我創建了一個TMP user_struc可變讓我的指針函數指針的大小,因爲我沒能做到這一點更清潔的方式。」

您可以使用user對象來計算構件的尺寸:

sizeof (user.pred_skip_func) 

或使用C99複合文字,如果您還沒有聲明的結構類型的任何對象:

sizeof (((struct user_s) {0}).pred_skip_func) 
+0

在這個例子中,struct用戶有靜態存儲?對我來說不是。所以我不清楚。 – 2012-08-03 11:40:18

+2

@ManuelSelva:在文件範圍聲明的變量具有*靜態存儲持續時間*。 – Jon 2012-08-03 11:41:02

+0

好的。因此,將全局變量聲明爲靜態不會影響「存儲時間」,但我們怎麼稱呼它? – 2012-08-03 11:42:31

2

正如@ouah指出的那樣,問題是pred_skip_func不是一個常數值。編譯器會抱怨,因爲user具有靜態存儲持續時間,這意味着它的按位表示將在鏈接時「在可執行映像中烘焙」。爲了讓鏈接器知道該表示,pred_skip_func的值必須是常數。

然而,你可以非常容易地指定結構部件「理智默認」的恆定值:

struct user_s user = {"Manu", 0}; 
1

你可以去typedefs的函數指針像下面。

typedef void (*pfunc_type)(int); 

struct user_s 
{  
    char *name;  
    pfunc_type *pred_skip_func; 
}; 

..... 

int main (void) 
{ 
    ..... 
    pred_skip_func = (pfunc_type *)malloc(sizeof(pfunc_type) * 2); 
    ..... 
} 

這會增加程序的可讀性。