Returning struct from different file in C - c

Lately I've encountered a problem of returning struct from another file in C language.
Here's the code of main.c:
#include <stdio.h>
#include <stdlib.h>
#include "hash_types.h"
int main()
{
hashinfo info;
info = numerator();
printf("%d\n", info.ppower);
return 0;
}
And numerator.c:
#include <stdlib.h>
#include <stdio.h>
#include "hash_types.h"
hashinfo numerator()
{
hashinfo info;
info.ppower = 15;
return info;
}
Here's what header file looks like:
typedef struct hashinfo{
unsigned long a_str;
unsigned long a_int;
unsigned long b_int;
unsigned long p;
unsigned long m;
char w;
char ppower;
}hashinfo;
When I try to compile the code, gcc fails to compile main reporting that
main.c: In function ‘main’:
main.c:10:7: error: incompatible types when assigning to type ‘hashinfo’ from type 'int'
info = numerator();
^
If I put all of these in the one file and compile, it will work just fine. What am I doing wrong? Thanks in advance.

You have to declare your numerator function everywhere where you want to use it. This is what the minimal declaration would look like
hashinfo numerator();
But a better idea would be to declare it with prototype
hashinfo numerator(void);
and do the same thing in the definition.
A typical approach would be to put the declaration into a header file and include it everywhere you what to use this function. Whether your hash_types.h is the appropriate one is for you to decide.

You have no way to telling your main what numerator() returns without including it somehow. It's generally considered bad practice to include a .c file, but try to add #include "numerator.c" to the top of main.c to see.

Add the declaration for numerator() in the header file hash_types.h. Add this at the end of hash_types.h: hashinfo numerator();

So how do you think that the main.c part (top) would know what type that numerator() returned? How would you inform main.c that it will reference functions of specific signatures? Potentially, you could create a separate file containing nothing but prototypes for your functions and have all modules include it. "proto.h" or similar.
Mark

Related

How to declare global variable for an anonymous structure in C?

I am using Pelles C on Windows 8.1.
How to declare single global variable for a structure in C?
Code 1: it works but I do not want any other object of the same type to be created. If code 2 has problems then I will have to use this one.
Single.h
struct single{
int x;
};
extern struct single oneAndOnly;
void initSingle(void);
void printSingle(void);
Single.c
#include <stdio.h>
#include "Single.h"
struct single oneAndOnly;
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Main.c
#include "Single.h"
int main()
{
initSingle();
printSingle();
return 0;
}
Code 2: It works but I am not clear about the combination of declaring and defining a variable in a header file. Will it cause a problem? I get no error though.
Single.h
struct{
int x;
}oneAndOnly;
void initSingle(void);
void printSingle(void);
Single.c
#include <stdio.h>
#include "Single.h"
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Main.c is the same as in Code 1.
Can I use code 2 without any problem?
Can someone tell me why does code 2 work, when I and many others thought that it would not?
Thanks to everyone for all your comments and ideas and answers
There is a third variant which might be of interest.
It "hides" the struct single completely in Single.c. Hence, no accidental access is possible.
Single.h:
void initSingle(void);
void printSingle(void);
Single.c:
#include <stdio.h>
#include "Single.h"
struct Single {
int x;
};
static struct Single oneAndOnly;
void initSingle(void)
{
oneAndOnly.x = 10;
}
void printSingle(void)
{
printf("x = %d\n", oneAndOnly.x);
}
main.c:
#include "Single.h"
int main()
{
initSingle();
printSingle();
return 0;
}
Live Demo on Wandbox
Actually, this approach is similar to P__J__'s answer. I just was too slow to press the Send button.
I needed some time to realize that the solution in quest should prevent an (accidental) second variable of the type of oneAndOnly.
"Hiding" the struct in the C file with a static instance is probably the best one can have in C. Even the counter examples in melpomene's answer shouldn't work in this case.
If read/write access to the single instance is required, I would add something like "getter"/"setter" functions.
This reminded me to the Singleton pattern though I'm not sure if that is a legal usage for a non-OO language like C. Googling a bit, I found (as well) How to create a Singleton in C? which I find worth to mention.
I googled a bit concerning the actual question of OP whether her/his Code 2 is valid as well. I suspected something like a duplicated definition (may be, because I did too long in C++ in daily work).
Actually, I tried OP's Code 2 in Wandbox – no duplicate definition issue. Finally, I found Are the global variables extern by default or it is equivalent to declaring variable with extern in global? and came to the conclusion that Code 2 should be fine as well.
The limitation is that Code 2 allows only default initialization (filling with 0s if I remember right). As soon as an initializer is added, the compiler complains (as expected) as it's included multiple times.
You call the function in other compilation unit. It uses the global variable not your main program. So you do not even have to know the data structure and the variable, as you newer use any of them in your main program.
you can reduce it to :
void initSingle(void);
void printSingle(void);
int main()
{
initSingle();
printSingle();
return 0;
}
and
#include <stdio.h>
struct{
int x;
}oneAndOnly;
static struct single oneAndOnly;
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
None of your attempts will work in practice.
With e.g. gcc or clang I can just do
typeof(oneAndOnly) secondInstance;
gcc also supports
__auto_type secondInstance = oneAndOnly;
(not sure about clang).
Even if the compiler in question doesn't support these extensions, I can just copy/paste the anonymous struct declaration from the header.
That said, I don't see what preventing other objects of the same type buys you. It makes sense in Java to make the constructor private because a constructor has behavior whose use you may want to restrict, but in C structs are just dumb collections of data.

Using structs in multiple files

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.

About accessing structs defined in different source file

Not any homework, but seem to have got lost while doing basics, hence asking.
Say I have 2 C source files. 1.c & 2.c
2.c is as follows:
typedef struct mystr_
{
int a;
float b;
}mystr;
void fun()
{
mystr q;
some code....
}
And 1.c is as below:
#include "stdio.h"
void fun();
main()
{
//How to access / declare a variable of type mystr here.
mystr *v1;//This obviously gives compiler errors
some code....
}
How to access the structure mystr defined in 2.c from file 1.c to have variables of that struct type there?
EDIT:
Sorry forgot to mention in OP. I cannot move the declaration out in a header file for some reason --> It is a quick hack that I am trying to check in a existing code. Then is there any way to access it directly from the other source file?
Use headers.
Create a file 2.h
typedef struct mystr_
{
int a;
float b;
}mystr;
And include it in 1.c
#include "2.h"
#include "stdio.h"
void void fun();
EDIT:
Because you are not able to extract the declaration into a header file and include it, there is no other way than copying the declaration. This is a highly fragile construct, quick but mainly dirty and not really recommended unless you are out of other options.

issues with structure with a pointer to it in a header file in c

`"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;

Why do I need to cast a struct returned from a function?

In one file I have this:
#include <stdio.h>
#include <stdlib.h>
static struct node* mynode;
struct node*
example(void)
{
mynode = malloc(sizeof(struct node));
...fill up the struct here...
return mynode;
}
The calling routine is:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
mynode=example();
}
The node itself is defined in a defs.h file I don't show here.
The warning I get when compiled with gcc is "assignment makes pointer from integer without a cast" in the calling routine.
Changing to mynode=(struct node*)example(); removes that warning. The routine works in any case but I don't understand why I'm getting the warning.
Could it be you didn't declare a prototype for struct node* example(void) and the compiler thinks it returns an int ?
In the file calling example, the return type of example is not known, so it is assumed to return an int, which you assign to struct node *. Hence the warning.
You should either declare the prototype for example in the calling file (typing in struct node* example(void); before the calling function) or (better) create a header file called, say, example.h, where you type in the prototype and then include the header file in the calling file (that is, typing in #include "example.h" at the top). The header file thus defines the interface of the file whereexample` is located, and the files using the functions can include the header file, thus making sure all the types match, and removing any compiler warnings.

Resources