如何将sizeof运算符应用于函数指针并初始化结构?

时间:2012-08-03 11:29:13

标签: c pointers struct

下面的代码片段生成错误:初始化元素不是常量 在编译时在行上声明并初始化用户struct变量。

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

在main函数中移动初始化可以解决问题,但我想了解原因?结构初始化是否有任何限制?

更多,正如你所看到的,我创建了一个tmp user_struc变量来获取指向函数指针的指针的大小,因为我无法以更干净的方式执行此操作。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

第一个问题:

“结构初始化是否有任何限制?”

C要求具有静态存储持续时间的聚合类型的初始值设定项为常量:

  

(C99,6.7.8p4)“具有静态存储持续时间的对象的初始值设定项中的所有表达式都应是常量表达式或字符串文字。”

请注意,在C89中,即使聚合类型的对象具有自动存储持续时间,初始化器也必须是常量表达式(在C99中不再是这种情况)。

第二个问题:

“更多内容,正如您所看到的,我创建了一个tmp user_struc变量来获取指向函数指针的指针的大小,因为我无法以更清晰的方式执行此操作。”

您可以使用user对象来计算成员的大小:

sizeof (user.pred_skip_func)

如果尚未声明任何结构类型的对象,则使用C99复合文字:

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

答案 1 :(得分:2)

正如@ouah所指出的那样,问题是pred_skip_func不是一个常数值。编译器抱怨因为user具有静态存储持续时间,这意味着它的按位表示将在链接时“覆盖”可执行映像。为了使链接器知道此表示,pred_skip_func的值必须是常量。

但是,您可以非常轻松地为结构成员指定“合理的默认”常量值:

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

答案 2 :(得分: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); 
    .....
}

这会增加程序的可读性。