【问题标题】:C: "invalid use of undefined type ‘struct X’ & dereferencing pointer to incomplete type" errorsC:“无效使用未定义类型‘struct X’和取消引用指向不完整类型的指针”错误
【发布时间】:2011-05-09 22:29:25
【问题描述】:

几天来,我一直在仔细研究与我类似的问题,但仍未找到解决方案。感谢任何帮助:

我有两个文件,一个包含处理有理数的方法,另一个包含在二维数组中处理它们的方法。我的问题是 matrix.c 无法识别 fraction.c 中包含的分数结构。我相信我的问题与我声明二维数组的方式有关。

在分数.c 中:

struct fraction {
   int integer;
   int num;
   int den;
};
typedef struct fraction* fractionRef;  //This line is in fraction.h

在matrix.c中:

#include "fraction.h"

typedef struct matrix* matrixRef;

struct matrix {
   int rows;
   int columns;
   fractionRef *m;
}matrix;

matrixRef new_matrix ( int rows, int columns ) {
   matrixRef matrix;
   matrix = (matrixRef)malloc( sizeof( matrix ) );
   matrix->m = (fractionRef*)calloc( rows, sizeof( fractionRef ) );
   int i;
   for ( i=0; i<=rows; i++ )
     matrix->m[i] = (fractionRef)calloc( columns, sizeof( fractionRef ) );
   assert( matrix->m );
   return matrix;

}
void free_matrix ( matrixRef freeMe ) {
   if ( freeMe != NULL ){
      int i, j;
      for( i = 0; i <= freeMe->rows; i++ ){
         for ( j = 0; j <= freeMe->columns; j++ ){
            free_fraction( freeMe->m[i][j] ); //ERROR OCCURS HERE
         }
      }
      freeMe->rows = 0;
      freeMe->columns = 0;
      free(freeMe);
      freeMe = NULL;
   }
}

我得到的错误对应matrix.c中我标记的行。

matrix.c:47: error: invalid use of undefined type ‘struct fraction’
matrix.c:47: error: dereferencing pointer to incomplete type

这可能都是因为我在c之前学过java,大错特错!!!再次感谢您的帮助。

编辑:谢谢大家。所以我现在看到的方式是头 .h 文件中的所有内容都类似于 java 中的 public。我的分数结构定义对 c 编译器不是“公开的”,因此我的 matrix.c 无法访问它。

【问题讨论】:

  • 使用 C 时必须适应的一件事:publicprivate 之类的词并不完全适用,而 static 一词的含义与它在 Java 中的含义不同.当您在 C 语言中获得更高级以创建类似于私有成员的 structs 时,“有一些方法”。但是关于static:在C 中,在文件范围级别,这意味着“私有”——声明一个变量,无论您在头文件中放入什么,都无法从另一个.c 文件访问该变量。 static 在文件范围和函数范围有不同的效果。
  • 您是否分配了sizeof(fraction) 的任何内存并将其分配给某个元素matrix-&gt;m[i][j] = calloc(1, sizeof(fraction)) 某处?您不能仅仅将指针(您称之为fractionRef)分配给struct,您必须在某些时候分配实际的struct fractions,就像您为矩阵所做的那样。您可能只是没有包含该代码,这很好。只是想知道,既然您将该行标记为导致一些错误,我想知道。另外,我希望free_fraction() 必须具有struct fraction * 类型的参数。
  • 好的,我发现这里需要注意的地方比我最初想象的要多。在继续之前我必须问:您是否要创建 rows 个行指针,然后让每行包含 columns 个分数指针?或者您是否希望每一行包含 columns 个实际分数结构?如果是第一种情况,您必须单独分配每个结构分数。如果是第二个,您必须一次分配每一行分数。告诉我,然后我会编辑我的答案。

标签: c compiler-errors multidimensional-array


【解决方案1】:

您必须将struct 的定义移动到fraction.h 文件中。与 Java 不同,编译器和链接器不会“神奇地”导致一个 .c 文件引用另一个 .c 文件中的信息。 (如果您 #include 一个 .c 文件在另一个文件中,则可以这样做——这是个坏主意。)

指令

#include "fraction.h"

使头文件的文本内容被放置在该指令所在的行,就像通过剪切和粘贴一样。编译器一次处理一个输入文件,读取#include'd 文件,并且在编译该.c 文件时必须提供所有需要的信息。

为了帮助您理解,我将指出一种糟糕的方法来完成您的要求:只需将struct fraction 的结构定义剪切并粘贴到matrix.c 的顶部,紧挨在#include "fraction.h" 之前 - - 结果将编译。在 Java 中,编译器可能会抱怨您声明了一些重复的类型。在 C 中,您所做的是定义两个不同的结构,它们恰好具有相同的内存布局和相同的名称。从链接目标文件的角度来看,只需要相同的内存布局即可使它们可互换。

是的,这是您从 Java 中得到的一个误解。你在学习 C 真是太好了!

【讨论】:

  • +1 让 OP 更容易跨越 Java 和 C 之间的桥梁(我不知道 Java,所以我无法帮助 /that/)。
【解决方案2】:

struct fraction 定义移至“fraction.h”并

#include "fraction.h"

在“fraction.c”和“matrix.c”中

【讨论】:

    【解决方案3】:

    很难猜出你的意图,但我猜你需要传递一个指向 free_fraction 的指针。

    free_fraction( &(freeMe->m[i][j]) );
    

    【讨论】:

    • freeMe-&gt;m[i][j] 已经是一个指针——他 calloc()'d columnsfractionRefmatrix-&gt;m[i]fractionRef 是 OP 的指针类型。我没有看到 OP 将非零值分配给任何元素指针的任何地方,尽管 OP 可以省略它。事实上,您的代码会导致对free 的错误调用。只有&amp;(freeMe-&gt;m[i][0]) 是从calloc 返回的,那是在row 的分配中,因为&amp;(freeMe-&gt;m[i][0]) == freeMe-&gt;m[i]。这个答案引入了一个危险的错误。
    【解决方案4】:

    在那里,您可能还想更改定义。

    更好的方法让你了解发生了什么:

    struct fraction {
       int integer;
       int num;
       int den;
    };
    typedef struct fraction fractionType; // We can now use fractionType and it'll be struct fraction
    
    typedef fractionType * fractionTypePtr; // We can now use fractionTypePtr and it will be a pointer to a fractionType which is a struct fraction
    

    【讨论】:

      【解决方案5】:

      或者,如果您确实想完全隐藏分数结构的实现,您可以在 fraction.h 中:

      typedef struct fraction* fractionRef;
      

      以及在 fraction.c 文件中实际声明的结构分数。

      但是,当您隐藏实现时,您还必须为可以对分数发出的所有操作定义函数,例如获取分子和分母的值,即编写如下内容:

      get_numerator(f);
      

      代替:

      f->num;
      

      【讨论】:

      • 如果你遵循这个建议,我不会,你还必须在 fraction.c 中创建一个分配结构分数的函数——因为 sizeof(struct fraction) 在外部无法知道分数.c.
      • 啊,是的,谢谢,我确实列出了所有分数方法,例如: int getNumerator(fractionRef); void setNumerator (fractionRef, int); fractionRef 添加(fractionRef,fractionRef);无效 printFr (fractionRef, int); ..等谢谢
      • 或者,您以面向对象的方式对待它,完全隐藏您的结构实现,并让结构仅包含指向可以作​​用于您的分数的函数的指针,以及指向分数的不透明指针本身。
      猜你喜欢
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多