如何修复 C 中的"incompatible type"错误?



我正在创建 * create Schedule () 函数来生成 ScheduleData 数据类型的计划,但我收到错误:分配给类型"ScheduleData"时类型不兼容。 有人可以帮助我如何解决这个问题吗?

在 Schedule * 函数 createSchedule () 中,在 schedule-> 行中,节点 [i] [j] = schData; 发生错误

struct ScheduleData {
char *initials;
char *classroom;
char *teacher;
};
struct Schedule {
ScheduleData node[8][6];
};
Schedule *createSchedule() {
Schedule *schedule = malloc(sizeof(Schedule));
ScheduleData *schData;
for (int i = 0; i < 8; i++)
for (int j = 0; j < 6; j++) {
schData = malloc(sizeof(ScheduleData));
schData -> initials = NULL;
schData -> classroom = NULL;
schData -> teacher = NULL;
schedule->node[i][j] = schData;
}
return schedule;
}

您的struct Schedule包含实际struct ScheduleData结构的数组;您尝试将指针分配给这些结构和编译器对象。 你不需要嵌套循环中的malloc()操作(或分配给schedule->node[i][j])——或者你需要ScheduleData *node[8][6];。 我建议不要在循环中使用malloc()

此外,正如Martin Rosenau在评论中指出的那样,C编译器不会在给定声明struct Schedule { … };的情况下生成名称Schedule(在"普通标识符"命名空间中)-尽管C++编译器会生成名称。 您需要添加:

typedef struct Schedule Schedule;
typedef struct ScheduleData ScheduleData;

在使用名称之前,ScheduleScheduleData没有前面的struct。 如果你写的是C++而不是C,那么你需要修复问题的标签,你需要停止使用malloc()等。 如果你必须在C++中使用malloc()et al,你将需要显式强制转换将void *转换为正确的类型 — 在 C 中不需要强制转换。

更少的malloc()呼叫

Schedule *createSchedule(void)
{
Schedule *schedule = calloc(sizeof(Schedule), 1);
return schedule;
}

使用calloc()会使结构中的所有字节归零,这通常会将所有指针设置为 NULL 等。 (调用代码有责任检查是否未返回空指针。 或者:

Schedule *createSchedule()
{
Schedule *schedule = malloc(sizeof(Schedule));
if (schedule != NULL)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 6; j++)
{
schedule->data[i][j].initials = NULL;
schedule->data[i][j].classroom = NULL;
schedule->data[i][j].teacher = NULL;
}
}
}
return schedule;
}

您也可以使用memset()malloc()提供的数据归零,但使用calloc()至少可以同样有效地做到这一点。

继续大量使用malloc()

struct Schedule类型更改为:

struct Schedule
{
ScheduleData *node[8][6];
};

请注意,这会使用更多的内存(每个分配都有开销),并且结构更难释放(您需要 49 次调用才能free()而不是 1 次)。

风格指南

  1. 在使用结果之前,请始终检查内存分配函数是否报告成功。
  2. 不要在点.或箭头->运算符周围留空格。 它们捆绑得非常紧密;该空间是不必要的、非常规的,并且使您的代码更难阅读。
  3. 请在函数声明和定义中使用显式Schedule *createSchedule(void)来指示没有参数。 C 不是C++;两者之间的规则是不同的。 明确void意味着编译器会警告你createSchedule(32, "pink elephants")而如果你没有明确指定void,它没有义务警告你滥用函数——如果你省略了void,你没有创建一个原型,只是一个函数声明。
Schedule *createSchedule(void)
{
// make sure you cast the return arg of malloc!
Schedule *schedule = (Schedule*)malloc(sizeof(Schedule));
// no need to allocate each 6x8node, already done
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 6; j++) {
schedule->node[j][i]->initials = NULL;
schedule->node[j][i]->classroom = NULL;
schedule->node[j][i]->teacher = NULL;
}
}
return schedule;
}

或者,由于计划中的每个字节都设置为 0,因此您可以在创建后在此处使用memset()

Schedule *createSchedule(void)
{
// make sure you cast the return arg of malloc!
Schedule *schedule = (Schedule*)malloc(sizeof(Schedule));
memset(schedule, 0, sizeof(Schedule));
return schedule;
}

如何修复C中的"不兼容类型"错误?

你需要问两个问题:

schedule->node[i][j]是什么类型?

答:ScheduleData

schData是什么类型?

答:它是ScheduleData *(即指向ScheduleData的指针)

由于这两个变量具有不同的类型,因此会出现编译错误。

要修复它,您需要更改其中一个变量的类型以匹配另一个变量。

从您的代码来看,您似乎希望将schedule->node[i][j]更改为ScheduleData *。所以你需要做的就是:

struct Schedule {    
ScheduleData *node[8][6];
//  notice   ^  
};

顺便说一句:您已经标记了问题C,但似乎您使用了C++编译器。如果您真的想要C++请修复标签。如果你真的想要 C,请使用 C 编译器。

我的回答不是实际的答案,而是对乔纳森·莱夫勒答案的延伸:

我经常读到像你这样的问题。在大多数情况下,将 C 和 C++ 与 Java 或 C# 进行比较会产生误解:

在Java中,原始数据类型(如int)的变量保存值,而class数据类型的值保存对对象的引用。

"参考"是指在以下程序中:

ScheduleData a = b;
a.initials = "ab";
b.initials = "xy";

。语句a.initialsb.initials访问相同的变量。

但是,C 和 C++的工作方式不同

您可以通过在数据类型和变量名称之间使用或不使用星号 (*) 来决定变量是"指针"(或多或少是"引用"),还是值。例:

ScheduleData a, *b;
int c, *d, *e;
d = e;

在此示例中,变量ac保存值,变量bde保存引用。

就像在 Java 示例中一样,修改d指向的值与修改e指向的值具有相同的效果,因为de是对同一整数的引用。

Jonathan Leffler 答案中的第一个解决方案建议使用数据类型ScheduleData的值,而不是使用引用。

第二种解决方案显示如何使用引用。避免引用通常使编程更容易,但如果要执行以下 Java 程序的等效操作,则可能需要引用:

ScheduleData x = node[4][2];
ScheduleData y = node[4][2];
node[4][2] = new ScheduleData();
/* x and y will be a reference to the same data structure but node[4][2]
* is a reference to a different data structure */

顺便一提

您编写的程序是C++程序,而不是 C 程序。

C++,C 语言不会自动将结构名称识别为数据类型。相反,您必须使用typedef来定义数据类型:

typedef struct _s_ScheduleData {
...
} ScheduleData;

。或者,您必须使用struct关键字作为数据类型的一部分:

struct ScheduleData node[8][6];

你可以用一个简单的赋值替换所有的循环:

Schedule *createSchedule(void) {
//                       ^^^^ use this to indicate no parameters
Schedule *schedule = malloc(sizeof(Schedule));
*schedule = (Schedule){0};
return schedule;
}

(Schedule){0}创建一个临时对象,初始值设定项意味着任何指针都将设置为 null 指针。

如果您的编译器很旧,则可以将赋值行替换为Schedule blank = {0}; *schedule = blank;

相关内容

最新更新