I'm trying to allocate dynamically a global struct in c, but something makes my c file not being able to find the reference to the extern variable.
The log:
main.c:18: undefined reference to `gate_array'
extern.h
#ifndef EXTERN_H_
#define EXTERN_H_
typedef struct gate_struct {
int out;
} gate;
extern gate *gate_array;
#endif /* EXTERN_H_ */
main.c:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "extern.h"
int main(int argc, char *argv[]){
gate_array = (gate*) malloc (2* sizeof(gate));
return 0;
}
Thanks!
There is no definition of gate_array due to extern. In this case, you can just remove the extern qualifier. However, if extern.h was used in multiple translation units (#include in several .c files) then this approach would result in multiple definition errors. Consider adding another .c file that would contain the definiton of gate_array (and any future variables), ensuring there is exactly one definition of gate_array.
The extern gate *gate_array tells the compiler that there is a variable called gate_array, but it is defined somewhere else. But there is no definition of gate_array in the posted code.
Also, you may wish to read
Do I cast the result of malloc?
This is probably what you meant to do:
#ifndef EXTERN_H_
#define EXTERN_H_
typedef struct gate_struct {
int out;
} gate;
typedef gate *gate_array;
#endif /* EXTERN_H_ */
This typedefs gate * to gate_array. Then in your main.c you want to do:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "extern.h"
int main(int argc, char *argv[]){
gate_array name_of_array = malloc (2* sizeof(gate));
free(name_of_array);
return 0;
}
Previously you were missing a variable name. Furthermore, it is bad practice to cast the return of malloc.
Pointer to gate i.e. gate_array was typedef not declared so you were doing something like this:
typedef int *IXX;
IXX = (int*) malloc(2*sizeof(int));
Do something like this:
IXX ix = (int*) malloc(2*sizeof(int));
Related
I am trying to create a struct that I will use in a function via pointers. The issue is that I do not want to use global variables therefore I can't use a pointer to a struct as a parameter for the function prototype if I try to define the struct in main file, since it has not been defined yet.
How would I go about doing this? What I think the solution is, is to define the struct in a header file, then create local variables of that type in the main file. Is this the right way to go about this? Would appreciate some info about what i'm actually doing here if this is correct.
Sorry if I did anything wrong when posting, Its my first time.
Example of what I am thinking the solution is
Main.h
#include <stdio.h>
typedef struct Vehicle{
int a;
char b;
};
function(Vehicle *p);
Main.c
#include "Main.h"
Vehicle Car1;
Vehicle *p=&Car1;
function(p);
The proper syntax for a typedef is
typedef T-IDENTIFIER IDENTIFIER-LIST;
wherein the comma separated identifiers listed in IDENTIFIER-LIST become aliases for T-IDENTIFIER. A lot of the time IDENTIFIER-LIST will consist of a single identifier.
For example, in
typedef int integer, number;
integer and number are now type aliases for int.
When it comes to using typedef with structs, the form
typedef struct foo { /* ... */ } foo_type;
is more or less shorthand for
typedef struct foo foo_type;
struct foo { /* ... */ };
but does allow you to typedef an anonymous struct
typedef struct { /* ... */ } foo_type;
With all that said, in your code you have omitted the IDENTIFIER-LIST from your typedef.
If main.c really does consist entirely of the code you've posted, it will not compile. Every C program needs an entry point, and in a hosted environment that is the function main with the signature int main(void) or int main(int argc, char **argv).
While you can declare variables outside of functions (i.e., globals), you can not call functions from outside of functions. Everything starts from main.
A working example program:
main.h:
typedef struct {
int a;
char b;
} Vehicle;
void function(Vehicle *p);
main.c:
#include <stdio.h>
#include "main.h"
int main(void) {
Vehicle car = { 51, 'A' };
function(&car);
}
void function(Vehicle *v) {
printf("Vehicle: a: %d, b: %c\n", v->a, v->b);
}
I can't use the struct as a parameter for the function prototype
You misunderstood something.
Your typedef is rather useless.
You of course can use pointers to structs as function parameters and in the function prototypes.
typedef struct {
int a;
char b;
} Vehicle;
int foo(Vehicle *); // prototype
You can't call function not outside other functions (as it is shown in the main.c
Is there a way to find the packed size of a structure defined and declared without packed attribute in GCC compiler?
Example:
struct Name
{
int a;
char ch;
}
any function or macro like get_packed_size(Name) should return 5
Define your struct using a macro that provides the required information. For example (though there are other possible implementations):
#define DEFINE_STRUCT_WITH_KNOWN_PACKED_SIZE(StructName, StructBody)\
struct StructName StructBody\
struct __attribute__ ((__packed__)) StructName##_packed StructBody
#define GET_PACKED_SIZE(StructName) sizeof (struct StructName##_packed)
DEFINE_STRUCT_WITH_KNOWN_PACKED_SIZE(Name, {
int a;
char ch;
};)
#include <stdio.h>
int main() {
printf("%lu", GET_PACKED_SIZE(Name));
}
No, there's no way... you only have sizeof(), and you need to take care of the padding...
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.
`"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 read about 5 different questions on the same error, but I still can't find what's the problem with my code.
main.c
int main(int argc, char** argv) {
//graph_t * g = graph_create(128); //I commented this line out to make sure graph_create was not causing this.
graph_t * g;
g->cap; //This line gives that error.
return 1;
}
.c
struct graph {
int cap;
int size;
};
.h
typedef struct graph graph_t;
Thanks!
You can't do that since the struct is defined in a different source file. The whole point of the typedef is to hide the data from you. There are probably functions such as graph_cap and graph_size that you can call that will return the data for you.
If this is your code, you should define struct graph inside the header file so all files that that include this header will be able to have the definition of it.
When the compiler is compiling main.c it needs to be able to see the definition of struct graph so that it knows there exists a member named cap. You need to move the definition of the structure from the .c file to the .h file.
An alternate method, if you need graph_t to be an opaque data type, is to create accessor functions that take a graph_t pointer and return the field value. For example,
graph.h
int get_cap( graph_t *g );
graph.c
int get_cap( graph_t *g ) { return g->cap; }
Must be the order you have things defined. The typedef line needs to show up in the header file that is included by the file that has main().
Otherwise it worked fine for me.
lala.c
#include "lala.h"
int main(int argc, char** argv) {
//graph_t * g = graph_create(128); //I commented this line out to make sure graph_create was not causing this.
graph_t * g;
g->cap; //This line gives that error.
return 1;
}
lala.h
#ifndef LALA_H
#define LALA_H
struct graph {
int cap;
int size;
};
typedef struct graph graph_t;
#endif
This compiles without problems with:
gcc -Wall lala.c -o lala