我正在创建 * 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;
在使用名称之前,Schedule
或ScheduleData
没有前面的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 次)。
风格指南
- 在使用结果之前,请始终检查内存分配函数是否报告成功。
- 不要在点
.
或箭头->
运算符周围留空格。 它们捆绑得非常紧密;该空间是不必要的、非常规的,并且使您的代码更难阅读。 - 请在函数声明和定义中使用显式
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.initials
和b.initials
访问相同的变量。
但是,C 和 C++的工作方式不同:
您可以通过在数据类型和变量名称之间使用或不使用星号 (*
) 来决定变量是"指针"(或多或少是"引用"),还是值。例:
ScheduleData a, *b;
int c, *d, *e;
d = e;
在此示例中,变量a
和c
保存值,变量b
、d
和e
保存引用。
就像在 Java 示例中一样,修改d
指向的值与修改e
指向的值具有相同的效果,因为d
和e
是对同一整数的引用。
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;
。