I am trying to call a function in main.c from io.h that reads data from a file, stores that data into multiple structs, then somehow lets me pass the different structs as arguments in later functions in main. Those later functions will be defined in other files, such as alg.h.
How do I go about doing this? Do I use extern and make the structs global and put them in a separate file? Is it possible to have a function from alg.h have a return type of one of the structs? Does it depend on the order of my includes?
The code pasted below complies and works, but any attempt to move either of the structs causes the program to not compile.
Also, is it possible to have, for example, a struct declared in alg.h, then functions that have that struct as a parameter declared later in alg.h. Then in main.c, you initialize and pass the struct into a function declared in io.h, give the struct some values, have it returned to main.c, then pass that into the function declared in alg.h? I know that sounds like a class, but I need a C solution and I only need one instance of the struct floating around.
Thanks.
io.h
struct s1 {
int num1;
double num2;
};
struct s2 {
int num3;
double num4;
};
void io_init(struct s1*, struct s2*);
io.c
#include <stdio.h>
#include <stdlib.h>
#include "io.h"
void io_init(struct s1* s1i, struct s2* s2i)
{
s1i->num1 = 5;
s1i->num2 = 2.4;
FILE *fp;
char line[80];
fp = fopen("input.txt","rt");
fgets(line, 80, fp);
sscanf(line,"%i",&s2i->num3);
fgets(line, 80, fp);
sscanf(line,"%i",&s2i->num4);
fclose(fp);
}
alg.h
void ga_init(struct s1);
alg.c
#include <stdio.h>
#include "io.h"
#include "ga.h"
void ga_init(struct s1 s1i)
{
printf("%i", s1i.val1);
}
main.c:
#include <stdio.h>
#include "io.h"
#include "ga.h"
int main() {
struct s1 s1i;
struct s2 s2i;
io_init(&s1i, &s2i);
ga_init(s1i);
return 0;
}
Every file which requires the declaration of your types (i.e., wants to use them) must include your header file (ok, so forward declarations and pointers will work, but they can't be dereferenced without the definition and that's not really applicable here anyway.)
So, to elaborate, if file X needs to use struct Y then it needs to include the header file which contains its declaration, that's it.
/* X.c */
#include "Y.h" /* <-- that's it! */
void foo(Y *obj) {
/* ... */
}
Here is some advice.
Your .h file is not defining struct objects. It's just defining the type. It's fine the way it is. Everyone who touches any struct of those types should include this file.
It's very rare to need to pass a struct by value as you are doing in the call to ga_init. You will essentially always want to call by reference, like you did with io_init.
Yes, you can return a struct, but again, it would almost always be better to return a reference to a struct.
You can certainly share globally defined structs and you don't need extern unless your linker is something awful. But sharing a reference to a struct allocated in main() amounts to roughly the same thing.
Related
So, I've been having a bit of confusion regarding linking of various things. For this question I'm going to focus on opaque pointers.
I'll illustrate my confusion with an example. Let's say I have these three files:
main.c
#include <stdio.h>
#include "obj.h" //this directive is replaced with the code in obj.h
int main()
{
myobj = make_obj();
setid(myobj, 6);
int i = getid(myobj);
printf("ID: %i\n",i);
getchar();
return 0;
}
obj.c
#include <stdlib.h>
struct obj{
int id;
};
struct obj *make_obj(void){
return calloc(1, sizeof(struct obj));
};
void setid(struct obj *o, int i){
o->id = i;
};
int getid(struct obj *o){
return o->id;
};
obj.h
struct obj;
struct obj *make_obj(void);
void setid(struct obj *o, int i);
int getid(struct obj *o);
struct obj *myobj;
Because of the preprocessor directives, these would essentially become two files:
(I know technically stdio.h and stdlib.h would have their code replace the preprocessor directives, but I didn't bother to replace them for the sake of readability)
main.c
#include <stdio.h>
//obj.h
struct obj;
struct obj *make_obj(void);
void setid(struct obj *o, int i);
int getid(struct obj *o);
struct obj *myobj;
int main()
{
myobj = make_obj();
setid(myobj, 6);
int i = getid(myobj);
printf("ID: %i\n",i);
getchar();
return 0;
}
obj.c
#include <stdlib.h>
struct obj{
int id;
};
struct obj *make_obj(void){
return calloc(1, sizeof(struct obj));
};
void setid(struct obj *o, int i){
o->id = i;
};
int getid(struct obj *o){
return o->id;
};
Now here's where I get a bit confused. If I try to make a struct obj in main.c, I get an incomplete type error, even though main.c has the declaration struct obj;.
Even if I change the code up to use extern, It sill won't compile:
main.c
#include <stdio.h>
extern struct obj;
int main()
{
struct obj myobj;
myobj.id = 5;
int i = myobj.id;
printf("ID: %i\n",i);
getchar();
return 0;
}
obj.c
#include <stdlib.h>
struct obj{
int id;
};
So far as I can tell, main.c and obj.c do not communicate structs (unlike functions or variables for some which just need a declaration in the other file).
So, main.c has no link with struct obj types, but for some reason, in the previous example, it was able to create a pointer to one just fine struct obj *myobj;. How, why? I feel like I'm missing some vital piece of information. What are the rules regarding what can or can't go from one .c file to another?
ADDENDUM
To address the possible duplicate, I must emphasize, I'm not asking what an opaque pointer is but how it functions with regards to files linking.
Converting comments into a semi-coherent answer.
The problems with the second main.c arise because it does not have the details of struct obj; it knows that the type exists, but it knows nothing about what it contains. You can create and use pointers to struct obj; you cannot dereference those pointers, not even to copy the structure, let alone access data within the structure, because it is not known how big it is. That's why you have the functions in obj.c. They provide the services you need — object allocation, release, access to and modification of the contents (except that the object release is missing; maybe free(obj); is OK, but it's best to provide a 'destructor').
Note that obj.c should include obj.h to ensure consistency between obj.c and main.c — even if you use opaque pointers.
I'm not 100% what you mean by 'ensuring consistency'; what does that entail and why is it important?
At the moment, you could have struct obj *make_obj(int initializer) { … } in obj.c, but because you don't include obj.h in obj.c, the compiler can't tell you that your code in main.c will call it without the initializer — leading to quasi-random (indeterminate) values being used to 'initialize' the structure. If you include obj.h in obj.c, the discrepancy between the declaration in the header and the definition in the source file will be reported by the compiler and the code won't compile. The code in main.c wouldn't compile either — once the header is fixed. The header files are the 'glue' that hold the system together, ensuring consistency between the function definition and the places that use the function (references). The declaration in the header ensures that they're all consistent.
Also, I thought the whole reason why pointers are type-specific was because the pointers need the size which can vary depending on the type. How can a pointer be to something of unknown size?
As to why you can have pointers to types without knowing all the details, it is an important feature of C that provides for the interworking of separately compiled modules. All pointers to structures (of any type) must have the same size and alignment requirements. You can specify that the structure type exists by simply saying struct WhatEver; where appropriate. That's usually at file scope, not inside a function; there are complex rules for defining (or possibly redefining) structure types inside functions. And you can then use pointers to that type without more information for the compiler.
Without the detailed body of the structure (struct WhatEver { … };, where the braces and the content in between them are crucial), you cannot access what's in the structure, or create variables of type struct WhatEver — but you can create pointers (struct WhatEver *ptr = NULL;). This is important for 'type safety'. Avoid void * as a universal pointer type when you can, and you usually can avoid it — not always, but usually.
Oh okay, so the obj.h in obj.c is a means of ensuring the prototype being used matches the definition, by causing an error message if they don't.
Yes.
I'm still not entirely following in terms of all pointers having the same size and alignment. Wouldn't the size and alignment of a struct be unique to that particular struct?
The structures are all different, but the pointers to them are all the same size.
And the pointers can be the same size because struct pointers can't be dereferenced, so they don't need specific sizes?
If the compiler knows the details of the structure (there's a definition of the structure type with the { … } part present), then the pointer can be dereferenced (and variables of the structure type can be defined, as well as pointers to it, of course). If the compiler doesn't know the details, you can only define (and use) pointers to the type.
Also, out of curiosity, why would one avoid void * as a universal pointer?
You avoid void * because you lose all type safety. If you have the declaration:
extern void *delicate_and_dangerous(void *vptr);
then the compiler can't complain if you write the calls:
bool *bptr = delicate_and_dangerous(stdin);
struct AnyThing *aptr = delicate_and_dangerous(argv[1]);
If you have the declaration:
extern struct SpecialCase *delicate_and_dangerous(struct UnusualDevice *udptr);
then the compiler will tell you when you call it with a wrong pointer type, such as stdin (a FILE *) or argv[1] (a char * if you're in main()), etc. or if you assign to the wrong type of pointer variable.
this error seems very easy to fix but i've been trying and have no clue.
So i have three files:
symtable.h:
typedef struct symbolTable *SymTable_T;
symtablelist.c:
#include "symtable.h"
struct Node{
char* key;
void* value;
struct Node* next;
};
struct symbolTable{
struct Node* head;
int length;
};
SymTable_T SymTable_new(void){
/* code */
}
And main.c:
#include "symtable.h"
int main(int argc, const char * argv[]) {
// insert code here...
SymTable_T emptyTable = SymTable_new();
emptyTable->length = 3; <------- ERROR
return 0;
}
I'm getting error: Incomplete definition of type "struct symbolTable"
Can anyone please give me a hint?
The reason i declare my struct in my source file is that i will have another implementation for the header file. so is there another way to fix my bug beside moving my struct declaration?
You can't access the members directly with an opaque pointer - if you keep the implementation in a separate source file, you'll have to access all the members via your interface, and not directly mess with the struct.
For instance, add this to symtable.h:
void SymTable_set_length(SymTable_T table, int len);
this to symtablelist.c:
void SymTable_set_length(SymTable_T table, int len)
{
table->length = len;
}
and in main.c change this:
emptyTable->length = 3;
to this:
SymTable_set_length(emptyTable, 3);
although in this specific case passing the length as an argument to SymTable_new() is an obviously superior solution. Even more superior is not letting the user set the length of a linked list data structure at all - the length is the number of items in it, and it is what it is. It would make no sense to, for instance, add three items to the list, and then allow main.c to set the length to 2. symtablelist.c can calculate and store the length privately, and main.c can find out what the length is, but it doesn't make much sense for main.c to be able to set the length directly. Indeed, the whole point of hiding the members of a struct behind an opaque pointer like this is precisely to prevent client code from being able to mess with the data like that and breaking the data structure's invariants in this manner.
If you want to access the members directly in main.c, then you have to have the struct definition visible, there is no alternative. This will mean either putting the struct definition in the header file (recommended) or duplicating it in main.c (highly unrecommended).
In typedef symbolTable *SymTable_T;, you refer to a non-existent type symbolTable. In C (unlike C++) the type is named struct symbolTable. (Note: the question has changed to fix this since answering it.)
There's a second problem. In main.c the code will need to be able to see the definition of struct symbolTable for you to be able to refer to fields of emptyTable. At the moment, the definition is hidden in a .c file... it should be moved to the header.
Consider the following struct defined in ModuleA:
typedef struct{
int A;
int B;
int C[4];
}myStructType;
myStructType MyStruct;
If I wanted to use this struct from ModuleB, then I would declare the struct in the ModuleA header like this:
extern myStructType MyStruct;
So far, so good. Other modules can read and write MyStruct by including the Module A header file.
Now the question:
How can I declare only part of the struct in the Module A header file? For example, if I wanted ModuleB to be able to read and write MyStruct.C (or, to make things a bit easier, perhaps MyStruct.A or MyStruct.B), but not necessarily know that it's in a struct or know about elements A and B.
Edit: I should probably also specify that this will go in an embedded system which does basically all of its memory allocation at compile time, so we can be extremely confident at compile time that we know where MyStruct is located (and it's not going to move around).
Edit2: I'll also clarify that I'm not necessarily trying to prevent other modules from accessing parts of the struct, but rather, I'm attempting to allow other modules to access individual elements without having to do MyStruct.Whatever because other modules probably only care about a single element and not the whole structure.
You would have to encapsulate it, i.e. make a private variable such as:
static myStructType the_struct;
in some C file, and then provide an API to get access to the parts:
int * getC(void)
{
return the_struct.C;
}
this would then let other C files get access to an integer array by calling
int *some_c = getC();
some_c[0] = 4711;
or whatever. It can be made "tighter" by being more explicit about the length of the returned array of course, I aimed for the minimal solution.
While in theory there might be some problems with the cleanliness of this solution (e.g. structure alignment), in practice it usually works if it compiles and if it doesn't compile, you can alter the structures to make it compile:
#include <stddef.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
// You keep this definition private to module A (e.g. in a .c file):
typedef struct
{
int A;
int B;
int C[4];
} PrivateStruct;
// You expose this definition to all modules (in an .h file):
typedef struct
{
char reserved[2*sizeof(int)];
int C[4];
} PublicStruct;
// You put these in module A (in a .c file):
C_ASSERT(sizeof(PrivateStruct) == sizeof(PublicStruct));
C_ASSERT(offsetof(PrivateStruct,C) == offsetof(PublicStruct,C));
int main(void)
{
return 0;
}
In the public .h file you can lie to the world about the global variable type:
extern PublicStruct MyStruct; // It's "PrivateStruct MyStruct;" in module A
If the two structure definitions go out of sync, you get a compile-time error (match, mismatch).
You will need to manually define the size of the reserved part of PublicStruct, perhaps by trial and error.
You get the idea.
To make the long story short — you can't. To make it a bit longer, you can't reliably do it.
You could try to use a kind of getter:
in ModuleA:
typedef struct{
int A;
int B;
int C[4];
}myStructType;
myStructType MyStruct;
int getA()
{
return MyStruct.A;
}
and so on.
Instead switch over to c++
You can't do exactly what you've described but it's common to have a struct used as a header, which is contiguous with a buffer which has it's internals only known to a particular module.
It's fairly obvious what this struct is the header for, but it still works as an example:
typedef struct _FILE_NOTIFY_INFORMATION {
ULONG NextEntryOffset;
ULONG Action;
ULONG NameLength;
ULONG Name[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
This struct (from Microsofts NativeSDK) is designed to be the header of a variable length buffer. All modules can work out how long the buffer is by looking at NameLength but you could use this method to store anything in the buffer which goes with it. That might only be known by a particular module with the others just using the length to copy it etc..
If it not for hiding but for structuring, then do structure it. For example like so:
moduleA.h:
typedef struct{
int A;
}myStructModuleAType;
extern myStructModuleAType myStructModuleA;
moduleA.c:
myStructModuleAType myStructModuleA;
moduleB.h:
typedef struct{
int B;
}myStructModuleBType;
extern myStructModuleBType myStructModuleB;
moduleB.c:
myStructModuleBType myStructModuleB;
main.h:
#include "moduleA.h"
#include "moduleB.h"
typedef struct{
myStructModuleAType * pmyStructModuleA;
myStructModuleBType * pmyStructModuleB;
int C[4];
}myStructType;
extern myStructType myStruct;
main.c:
#include "main.h"
myStructType myStruct;
myStructType myStruct = {
.pmyStructModuleA = &myStructModuleA
.pmyStructModuleB = &myStructModuleB
};
`"a.h"
typedef struct a
{
File* fp;
int var;
};
extern a *pp;
---------------------
"a.c"
int show(a* ptr)
{
printf("%d",ptr->var); //ptr has no member named var
}
---------------------
"main.c"
#include"a.h"
main()
{
a *pp=(a*)malloc(sizeof(a));
printf("%d",pp->var);// pp has no member named var
show(pp);
}
in the two print statements above, it gives me an error that a certain member of the struct is not present. did i miss anything? is there something i must do in addition?
i have a situation like this- very similar, not exact. please help. it is very important and i dont have much time.
That won't even compile, let alone run. You have do active definition for a in a.c, your typedef is incomplete, File should be FILE (and you should include stdio.h), and that's about where I stopped reading and started rewriting. If you post code to demonstrate a problem, make sure you post the right code, not just something you made up :-)
If you want a working solution to start with, go for a.h:
#include <stdio.h>
typedef struct {
FILE* fp;
int var;
} a;
and a.c:
#include "a.h"
int show(a* ptr) {
printf ("%d\n", ptr->var);
}
and, finally, main.c:
#include <stdio.h>
#include <stdlib.h>
#include"a.h"
int main (void) {
a *pp = malloc (sizeof (a));
printf ("%d\n", pp->var);
show (pp);
return 0;
}
Those will at least compile at which point you can begin the debugging process.
In a.c you forgot to include a.h so that the definition of the structure is not available.
Even though you have declared a variable pp, you forgot to actually define it. See External Variable.
On a side note - do not use typedef with structures where it is not necessary (i.e. the type is supposed to be an opaque type). C programmers like things to be clear and explicit. If it is a structure, a "struct" hint is very much appreciated and is worse a bit more typing.
Also, the "main" function must return an integer result code, preferably EXIT_SUCCESS or EXIT_FAILURE (defined in stdlib.h).
Try:
typedef struct
{
File* fp;
int var;
} a;
I have a strange problem in C about including header files.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "location.h"
int waste_new_line();
int main()
{
location *crossroads = malloc(sizeof(*crossroads));
...
location.h
typedef struct Location_Struct location;
location.c
typedef struct Location_Struct {
int ID;
char *name;
char *description;
} location;
int setup_location(location* l, char* name)
{
...
Now this isn't working because
location *crossroads = malloc(sizeof(*crossroads));
is throwing an error:dereferencing pointer to incomplete type meaning that it can see the contents of location.h, yet it doesn't seem to be aware of location.c...
I've looked around and all the tutorials I've seen say that the linker will link both files together.
EDIT:
I have altered the code to include an initializer inside location.c as so:
main.c
...
#include "location.h"
int waste_new_line();
int main()
{
location *crossroads = initialize_location();
....
location.h
typedef struct Location_Struct location;
location* initialize_location();
location.c
...
typedef struct Location_Struct {
int ID;
char *name;
char *description;
} location;
location* initialize_location(location* l)
{
return malloc(sizeof(location));
}
...
This is still throwing the same error, yet only when I try and access the members of crossroads using:
crossroads->description
this will throw the deferencing to incomplete type error.
EDIT 2: For now I've decided to just put the struct definition in the header file...
This behaviour is expected. When you #include "location.h", only the header file is visible to the compiler. The location.c file comes along later, at link time.
You have two options:
Add a function, which you declare in location.h and define in location.c, which does the necessary malloc and returns a pointer.
Move the full definition of the struct to the header file.
The main file knows about a struct called Location_Struct (and a typedef). It has no idea how big it is, thus you can't apply sizeof to it.
Since you are effectively hiding the layout and the implementation of Location_Struct it makes sense to provide a "constructor" that allocates it.
EDIT
It seems I have to mention that by "constructor" I mean an ordinary function that has access to the implementation of the structure and can allocate and possibly pre-populate the object.
You need to put the definition of Location_Struct in the header file location.h. The compiler would not "see" the other source file (unless it were #include'd, which would not typically be a good idea).