C: “invalid use of undefined type ‘struct X’ & der

2020-04-05 22:32发布

问题:

I've been perusing similar questions to mine for a couple of days but still haven't found a solution. Thanks any any help:

I have two files, one containing methods for dealing with rational numbers and one that handles them in a 2 dimensional array. My problem is matrix.c doesn't recognize the fraction structure in contained in fraction.c. I believe my problem is somehow related to the way I declared my 2d array.

In fraction.c:

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

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

The error I get corresponds to the line in matrix.c I marked.

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

This is probably all because I learned java BEFORE c, big mistake!!! Thanks again for any help.

EDIT: Thanks everyone. So the way I see it now is everything in the header .h files are similar to public in java. My fraction struct definition wasn't "public" to the c compiler so my matrix.c wasn't able to access it.

回答1:

You must move the definition of the struct into the fraction.h file. Unlike Java, the compiler and linker do not "magically" cause one .c file to reference information inside another .c file. (It could be done if you #include one .c file in another -- a bad idea.)

The directive

#include "fraction.h"

causes the text contents of the header file to be placed, as if by cut-and-paste, at the line with that directive. The compiler processes one input file at a time, reading in the #include'd files, and all the needed information must be present while that one .c file is compiled.

To help with your understanding, I will point out a terrible way to accomplish what you require: simply cut-and-paste the struct definition of struct fraction into the top of matrix.c, immediately prior to #include "fraction.h" -- the result will compile. In Java, the compiler might complain that you have declared some duplicate types. In C, what you've done is define two different structs, which happen to have an identical memory layout and the same name. Only the same memory layout is needed to make them interchangable from the perspective of linking together object files.

Yes, this is a misunderstanding you picked up from Java. It's wonderful that you are learning C!



回答2:

Move the struct fraction definition to "fraction.h" and

#include "fraction.h"

in both "fraction.c" and "matrix.c"



回答3:

It's hard to guess your intentions, but I'm guessing you need to pass a pointer to free_fraction.

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


回答4:

While in there, you may also want to change your definitions.

Better way so you understand what's going on:

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:

Alternatively, if you do want to totally hide the implementation of your fraction structure, you can have, in fraction.h:

typedef struct fraction* fractionRef;

and the actual declaration of your struct fraction in the fraction.c file.

However as you do hide the implementation, you must also define function for all the actions you can issue on a fraction, like, getting the value of numerator and denominator, i.e. writing things like:

get_numerator(f);

instead of:

f->num;