如何修复C语言中的“不兼容类型”错误?

时间:2019-07-15 05:37:13

标签: c types

我正在创建* 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;
}

5 个答案:

答案 0 :(得分:3)

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

此外,正如Martin Rosenau中提到的comment一样,给定声明Schedule,C编译器不会生成名称struct Schedule { … };(在“普通标识符”命名空间中) —尽管C ++编译器可以。您需要添加:

typedef struct Schedule Schedule;
typedef struct ScheduleData ScheduleData;

在使用名称ScheduleScheduleData而不使用前struct之前。如果您是使用C ++而不是C编写的,则需要修复问题的标签,并且需要停止使用malloc()等。如果必须在C ++中使用malloc()等,则需要显式强制转换将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];
};

请注意,这会占用更多的内存(每次分配都有开销),并且结构的释放也更加困难(您需要对free()进行49次调用,而不仅仅是1次)。

样式指南

  1. 在使用结果之前,请始终检查内存分配函数是否报告成功。
  2. 请勿在点.或箭头->运算符周围放置空格。它们紧密地捆绑在一起;该空间是不必要的,常规的,并且使您的代码更难阅读。
  3. 在函数声明和定义中都使用显式Schedule *createSchedule(void),以指示没有参数。 C不是C ++;两者之间的规则是不同的。并且明确声明void意味着编译器将警告您createSchedule(32, "pink elephants"),而如果您未明确指定void,则它没有义务警告您滥用该功能–如果您省略void,则不会创建原型,而只是创建函数声明。

答案 1 :(得分:2)

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

或者,由于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;
}

答案 2 :(得分:2)

  

如何修复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编译器。

答案 3 :(得分:1)

我的答案不是实际答案,而是对Jonathan Leffler's answer的扩展:

我经常阅读像您一样的问题。在大多数情况下,将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];

答案 4 :(得分:0)

您可以用简单的分配替换所有循环:

Schedule *createSchedule(void) {
//                       ^^^^ use this to indicate no parameters

    Schedule *schedule = malloc(sizeof(Schedule));
    *schedule = (Schedule){0};
    return schedule;
}

(Schedule){0}创建一个临时对象,并且初始化程序意味着所有指针都将设置为空指针。

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