0

次のコードではエラーが生成さ れます。ユーザー構造体変数を宣言および初期化する行で、コンパイル時に初期化子要素が定数ではありません。

#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 変数を作成しました。どうすればこれを修正できますか?

4

3 に答える 3

2

最初の質問:

「構造の初期化に制限はありますか?」

C では、静的ストレージ期間が一定である集約型の初期化子が必要です。

(C99、6.7.8p4) 「静的な保存期間を持つオブジェクトの初期化子のすべての式は、定数式または文字列リテラルでなければなりません。」

C89 では、集約型のオブジェクトに自動保存期間があったとしても、初期化子は定数式でなければならないことに注意してください (これは C99 では当てはまりません)。

2 番目の質問:

「さらに、ご覧のとおり、関数ポインターへのポインターのサイズを取得するために tmp user_struc 変数を作成しました。これをよりクリーンな方法で行うことができなかったからです。」

userオブジェクトを使用して、メンバーのサイズを計算できます。

sizeof (user.pred_skip_func)

または、構造体型のオブジェクトを宣言していない場合は、C99 複合リテラルを使用します。

sizeof (((struct user_s) {0}).pred_skip_func) 
于 2012-08-03T11:32:51.263 に答える
2

@ouah が指摘するように、問題はpred_skip_func定数値ではないことです。静的ストレージ期間があるため、コンパイラは不平を言いuserます。これは、そのビット単位の表現がリンク時に実行可能イメージに「焼き付けられる」ことを意味します。この表現がリンカーに認識されるためには、 の値pred_skip_funcは定数でなければなりません。

ただし、構造体メンバーの「適切なデフォルト」定数値を非常に簡単に指定できます。

struct user_s user = {"Manu", 0};
于 2012-08-03T11:38:17.473 に答える
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); 
    .....
}

これにより、プログラムの可読性が向上します。

于 2012-08-03T12:44:54.910 に答える