编译并执行以下代码段:
#include <stdlib.h>
typedef struct {
int count;
struct lval **cell;
} lval;
lval *lval_new(void) {
lval *v = malloc(sizeof(lval));
v->cell = NULL;
return v;
}
lval *lval_add(lval *x, lval *y) {
x->count++;
x->cell = realloc(x->cell, sizeof(lval *) * x->count);
x->cell[x->count - 1] = y;
return x;
}
int main() {
lval *x = NULL;
x = lval_new();
x = lval_add(x, lval_new());
}
将在gcc下生成以下警告:
foo.c:16:31: warning: incompatible pointer types assigning to 'struct lval *' from 'lval *' [-Wincompatible-pointer-types]
x->cell[x->count - 1] = y;
修改lval_add
的代码并在(struct lval*)
上添加y
广告,如下所示:
lval *lval_add(lval *x, lval *y) {
x->count++;
x->cell = realloc(x->cell, sizeof(lval *) * x->count);
x->cell[x->count - 1] = (struct lval *) y;
return x;
}
修复此警告。
对我来说这感觉不自然(免责声明:我不是一个熟练的C程序员),我必须添加几个演员来修复我的程序中的这些警告。
是否有更好的方法来声明lval
结构,以便它不会生成这些警告?
答案 0 :(得分:2)
您的结构不会被称为struct lval
。
试
typedef struct lv {
int count;
struct lv **cell;
} lval;
因为结构应该是struct lv
或lval
。
答案 1 :(得分:2)
在此声明中
typedef struct {
int count;
struct lval **cell;
} lval;
宣布了两个不同的实体。第一个是指向不完整类型struct lval
的双指针,第二个是带有别名lval
的未命名结构。
这就是宣言的这一部分
typedef struct {
在声明的这一部分
时启动未命名结构的定义 struct lval **cell;
又引入了一个不完整类型struct lval
的声明。
因此struct lval
和lval
表示不同的实体。
作为此转让声明的结果
x->cell[x->count - 1] = y;
左操作数的类型为struct lval *
,而右操作数的类型为lval *
,其中lval
是未命名结构的别名。
我认为你的意思是
typedef struct lval {
^^^^^^^^^^^^
int count;
struct lval **cell;
} lval;
在这种情况下,名称lval
是struct lval
类型的别名。
答案 2 :(得分:2)
在您的结构定义中,符号lval
尚不存在。在结构已经定义之前它不存在。然后不是作为结构而是作为类型名称。
有两种解决问题的方法,都需要你命名结构。
第一个非常接近你已经在做的事情:
typedef struct lval { // <- Note giving the structure a name
int count;
struct lval **cell; // <- Using the structure name
} lval;
第二种是在定义结构之前定义类型别名:
typedef struct lval lval; // Create type-name
struct lval {
int count;
lval **cell; // <- Use the type-name
};
另请注意,您不初始化结构的count
成员。这意味着它的值将是 indeterminate 并使用它可能会导致未定义的行为。
在lval_new
函数中,您需要明确地将其设置为零。