A question about global struct variable as a fuction's parameter

P

PCHOME

Hello! I am working on dividing a single C file into several files.
Now I encounter a problem about the global variables
and can not find a way to solve it.
All global variables and codes used to be in that single file, that
worked OK. But when I divdie that file into several ones, I
have many "invalid use of undefined type" errors.

The four files are main.c, main.h, readLP.h, and readLP.c.

In readLP.h
I have:

#define MAX_NUMROWS 181010
#define MAX_NUMCOLS 201
#define MAX_NUMNZ 9000000
....

typedef struct Polytope {
int rmatbeg[MAX_NUMROWS];
int rmatind[MAX_NUMNZ];
double rmatval[MAX_NUMNZ];
double rhs[MAX_NUMROWS];
char sense[MAX_NUMROWS];
double cosine[MAX_NUMROWS];
double norm[MAX_NUMROWS];
/* char *rowname[MAX_NUMROWS]; */
} a_polytope, aa_polytope;
....

and in main.h, I have:
....
extern struct Polytope a_polytope, aa_polytope ;

in main.c , if the external variable a_polytope is
used as a function's parameters such as :
status = CPXaddrows (env, lp, 0, num_rows, num_nonzero,
a_polytope.rhs, a_polytope.sense,a_polytope.rmatbeg,
a_polytope.rmatind, a_polytope.rmatval, NULL, NULL);
/* this is a CPLEX callable library function */

I will get "invalid use of undefined type `struct
Polytope'" error in compiling.
It was working OK when all codes were in sigle file without using
keyword "extern".

If I change main.h into:
....
extern struct Polytope a_polytope, aa_polytope ;
struct Polytope *pa_polytope, *paa_polytope ;
....
and also change main.c into
pa_polytope = &a_polytope ;
status = CPXaddrows (env, lp, 0,num_rows, num_nonzero,
pa_polytope->rhs,pa_polytope->sense,pa_polytope->rmatbeg,
pa_polytope->rmatind,pa_polytope->rmatval,
NULL, NULL);

I will get "dereferencing pointer to incomplete type"
four times for each pa_polytope->xxxx above.

Does anyone have a suggestion?

Thank you so much!
 
E

Eric Sosman

PCHOME said:
Hello! I am working on dividing a single C file into several files.
Now I encounter a problem about the global variables
and can not find a way to solve it.
All global variables and codes used to be in that single file, that
worked OK. But when I divdie that file into several ones, I
have many "invalid use of undefined type" errors.

The four files are main.c, main.h, readLP.h, and readLP.c.

In readLP.h
I have:

#define MAX_NUMROWS 181010
#define MAX_NUMCOLS 201
#define MAX_NUMNZ 9000000
...

typedef struct Polytope {
int rmatbeg[MAX_NUMROWS];
int rmatind[MAX_NUMNZ];
double rmatval[MAX_NUMNZ];
double rhs[MAX_NUMROWS];
char sense[MAX_NUMROWS];
double cosine[MAX_NUMROWS];
double norm[MAX_NUMROWS];
/* char *rowname[MAX_NUMROWS]; */
} a_polytope, aa_polytope;

Are you sure this is your code? It may be, of
course, but if so it doesn't mean what I suspect you
intend it to mean. This declaration says "Here is
what a `struct Polytope' looks like, and here are two
aliases for `struct Polytope' -- that is, any time I
write `a_polytope' or `aa_polytope' it is just as if
I had written out `struct Polytope' in full."

Note that this declaration does *not* declare or
define any variables of the type `struct Polytope' --
it just describes `struct Polytope' and creates two
aliases for it.
...

and in main.h, I have:
...
extern struct Polytope a_polytope, aa_polytope ;

This says "Somewhere else I will define two variables
of type `struct Polytope' with these two names." However,
nothing that you've shown actually defines any such
variables.

Another interesting point (the proximal cause of the
diagnostics you're receiving) is that the description of
what a `struct Polytope' looks like appears only in
"readLP.h". If you include "main.h" in a file that doesn't
also include "readLP.h", that description is not available.
The compiler knows that `struct Polytope' is some kind of
a struct type, but doesn't know anything about the elements
that struct type contains: it doesn't know their names,
their types, their sizes, or their arrangement within the
struct. (You will eventually learn that such "incomplete
types" can be useful in certain circumstances, but I think
you may not be quite ready for that lesson yet.)
in main.c , if the external variable a_polytope is
used as a function's parameters such as :
status = CPXaddrows (env, lp, 0, num_rows, num_nonzero,
a_polytope.rhs, a_polytope.sense,a_polytope.rmatbeg,
a_polytope.rmatind, a_polytope.rmatval, NULL, NULL);
/* this is a CPLEX callable library function */

I will get "invalid use of undefined type `struct
Polytope'" error in compiling.

Right: Without "readLP.h", the compiler is ignorant of
the internals of a `struct Polytope'. From the code as shown
it might deduce that the struct has elements named `rhs' and
`sense' and so on, but it has no idea what these names mean.
It was working OK when all codes were in sigle file without using
keyword "extern".

Presumably because the complete declaration of `struct
Polytope' was in that file, too. (But I suspect that the
`typedef' is a recent and probably incorrect addition.)
If I change main.h into:
...
extern struct Polytope a_polytope, aa_polytope ;
struct Polytope *pa_polytope, *paa_polytope ;
...
and also change main.c into
pa_polytope = &a_polytope ;
status = CPXaddrows (env, lp, 0,num_rows, num_nonzero,
pa_polytope->rhs,pa_polytope->sense,pa_polytope->rmatbeg,
pa_polytope->rmatind,pa_polytope->rmatval,
NULL, NULL);

I will get "dereferencing pointer to incomplete type"
four times for each pa_polytope->xxxx above.

Right: The compiler knows of two `struct Polytope'
variables ("Whatever *that* may be," says the compiler)
named `a_polytope' and `aa_polytope'. It also knows of
to pointers `pa_polytope' and `paa_polytope', defined
locally, that can be made to point to those structs (and
to others of the same type). But it's still without any
information about "the insides" of the struct; loosely
speaking, you've told it how to point "at" the struct as
a whole, but not how to "reach inside."
Does anyone have a suggestion?

Back to the C textbook, I think. There are enough
misunderstandings on exhibit here that you're probably
better off re-studying the fundamentals than trying to
blunder ahead in flat-Earthian ignorance -- you wouldn't
want to fall off the Edge, would you?
 
D

Darius

PCHOME said:
Hello! I am working on dividing a single C file into several files.
Now I encounter a problem about the global variables
and can not find a way to solve it.
All global variables and codes used to be in that single file, that
worked OK. But when I divdie that file into several ones, I
have many "invalid use of undefined type" errors.

The four files are main.c, main.h, readLP.h, and readLP.c.

In readLP.h
I have:

#define MAX_NUMROWS 181010
#define MAX_NUMCOLS 201
#define MAX_NUMNZ 9000000
...

typedef struct Polytope {
int rmatbeg[MAX_NUMROWS];
int rmatind[MAX_NUMNZ];
double rmatval[MAX_NUMNZ];
double rhs[MAX_NUMROWS];
char sense[MAX_NUMROWS];
double cosine[MAX_NUMROWS];
double norm[MAX_NUMROWS];
/* char *rowname[MAX_NUMROWS]; */
} a_polytope, aa_polytope;
...

and in main.h, I have:
...
extern struct Polytope a_polytope, aa_polytope ;

in main.c , if the external variable a_polytope is
used as a function's parameters such as :
status = CPXaddrows (env, lp, 0, num_rows, num_nonzero,
a_polytope.rhs, a_polytope.sense,a_polytope.rmatbeg,
a_polytope.rmatind, a_polytope.rmatval, NULL, NULL);
/* this is a CPLEX callable library function */

I will get "invalid use of undefined type `struct
Polytope'" error in compiling.
It was working OK when all codes were in sigle file without using
keyword "extern".

If I change main.h into:
...
extern struct Polytope a_polytope, aa_polytope ;
struct Polytope *pa_polytope, *paa_polytope ;
...
and also change main.c into
pa_polytope = &a_polytope ;
status = CPXaddrows (env, lp, 0,num_rows, num_nonzero,
pa_polytope->rhs,pa_polytope->sense,pa_polytope->rmatbeg,
pa_polytope->rmatind,pa_polytope->rmatval,
NULL, NULL);

I will get "dereferencing pointer to incomplete type"
four times for each pa_polytope->xxxx above.

Does anyone have a suggestion?

Thank you so much!

refer eric's reply to understand what you did wrongly.
now i'll tell you how can you correct this, i mean generally how its
done.

in readLP.h //remove typedef
/*typedef*/ struct Polytope {
int rmatbeg[MAX_NUMROWS];
int rmatind[MAX_NUMNZ];
double rmatval[MAX_NUMNZ];
double rhs[MAX_NUMROWS];
char sense[MAX_NUMROWS];
double cosine[MAX_NUMROWS];
double norm[MAX_NUMROWS];
/* char *rowname[MAX_NUMROWS]; */
} ;
extern struct Polytope a_polytope, aa_polytope;

in readLP.c
#include "readLP.h"
struct Polytope a_polytope, aa_polytope;

in any other file -------->
#include "readLp.h"
// optionally you can declare extern struct Polytope a_polytope,
aa_polytope;
//its your wish as it has already been done when you include readLP.h

rest is fine !!!
 
P

PCHOME

Eric said:
Presumably because the complete declaration of `struct
Polytope' was in that file, too. (But I suspect that the
`typedef' is a recent and probably incorrect addition.)
Yes. The `typedef' is a recent addition. I did not put it in my
orginalcodes. I added it desperately after dozens of trials.


Back to the C textbook, I think. There are enough
misunderstandings on exhibit here that you're probably
better off re-studying the fundamentals than trying to
blunder ahead in flat-Earthian ignorance -- you wouldn't
want to fall off the Edge, would you?
What C textbook will you suggest? I did look up at least 3
C-textbooks, but none of them mentions clearly about the topics of
"#include" and mutiple files project.

Thanks!
 
P

PCHOME

Darius wrote:

extern struct Polytope a_polytope, aa_polytope;

in readLP.c
#include "readLP.h"
struct Polytope a_polytope, aa_polytope;

in any other file -------->
#include "readLp.h"
// optionally you can declare extern struct Polytope a_polytope,
aa_polytope;
//its your wish as it has already been done when you include readLP.h

rest is fine !!!
Do you mean that #include "readLp.h" is necessary in any other file
using struct Polytope a_polytope? but "extern struct Polytope
a_polytope" is optional?
Thanks!
Somehow, I do not know why I used to believe that putting the same '
#include "readLP.h" ' into more than 2 different c files would lead
mutiple definitions of variables. Now I know it is OK to do so.
Is it also OK to put 'int test_i = 0;' into that "readLP.h" and
include it in more than on files?
I might be wrong,but to me the 'int test_i = 0;' is a declaration puls
a definition.
I know it is OK to have 'int test_i;' in it becasue 'int test_i;' is
just a declararion. How about puting 'int test_i = 0' there? The
latter is a definition to me(I might be wrong here).

I looked up several C books before but could not find one clearly
describe topics about mutiple c files project, #incldue and other
preprocessor commands, and so on. Do you happen to know which C book
touch those topics in depth?
Thanks!
 
D

Darius

PCHOME said:
Darius wrote:


Do you mean that #include "readLp.h" is necessary in any other file
using struct Polytope a_polytope? but "extern struct Polytope
a_polytope" is optional?

yes even this code is valid
int func()
{
extern int a; // for some global variable a;
extern int a;
extern int a;
}
Thanks!
Somehow, I do not know why I used to believe that putting the same '
#include "readLP.h" ' into more than 2 different c files would lead
mutiple definitions of variables. Now I know it is OK to do so.

here is a catch; to save yourself from multiple definations

do this
<------------------------------readLP.h--------------------------------->

#ifndef PCHOME_READLP_H
#define PCHOME_READLP_H

<-----------here is all the code-------------->

#endif

you can use any identifier (a unique string) instead of READLP_H, in
this way
when you include that file first time PCHOME_READLP_H is defined and
next time becoz its already defined, the content is not included again.
you got it?

Is it also OK to put 'int test_i = 0;' into that "readLP.h" and
include it in more than on files?

yes!!!, if you follow the rules above, else you'll get double
defination error
but i don't write any defination in .h files. just declare it using
'extern'
I might be wrong,but to me the 'int test_i = 0;' is a declaration puls
a definition.
I know it is OK to have 'int test_i;' in it becasue 'int test_i;' is
just a declararion. How about puting 'int test_i = 0' there? The
latter is a definition to me(I might be wrong here).

I think its clear now.
I looked up several C books before but could not find one clearly
describe topics about mutiple c files project, #incldue and other
preprocessor commands, and so on. Do you happen to know which C book
touch those topics in depth?
Thanks!

kernighan & ritchie and C unleashed (rest you'll learn by experience)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,600
Members
45,179
Latest member
pkhumanis73
Top