C Global Struct Pointer - c

I have a typedef'ed structure declared in a file. I have a pointer to it and want to use it in multiple files as a global variable. Can someone point out what I am doing wrong?
fileA.h:
typedef struct
{
bool connected;
char name[20];
}vehicle;
extern vehicle *myVehicle;
fileA.c:
#include "fileA.h"
void myFunction(){
myVehicle = malloc(sizeof(vehicle));
myVehicle->connected = FALSE;
}
fileB.c:
#include "fileA.h"
void anotherFunction(){
strcpy(myVehicle->name, "this is my car");
}
The error I get is:
Undefined external "myVehicle" referred to in fileA

This is a declaration:
extern vehicle *myVehicle; /* extern makes this a declaration,
and tells the compiler there is
a definition elsewhere. */
Add a definition:
vehicle *myVehicle;
to exactly one .c file.

Related

pointer to struct in function prototype before defining struct

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

Rudimentary OOP in C

Experimenting with primitive OOP ideas in C.
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "reptile.h"
int main()
{
const char *name = "Spot";
turtle_t *t = maketurtle(name);
t->hide(t); // <---- "Error: dereferencing pointer to incomplete type"
return 0;
}
reptile.h:
#ifndef REPTILE_H
#define REPTILE_H
typedef struct turtle_t turtle_t;
turtle_t* maketurtle(const char *name);
void hide(turtle_t *self);
#endif // REPTILE_H
reptile.c:
#include <stdio.h>
#include <stdlib.h>
#include "reptile.h"
typedef struct turtle_t
{
int numoflegs;
const char name[25];
void (*hide)(turtle_t *self);
} turtle_t;
turtle_t* maketurtle(const char *name)
{
turtle_t *t = (turtle_t*)malloc(sizeof(turtle_t));
t->name = name;
return t;
}
void hide(turtle_t *self)
{
printf("The turtle %s has withdrawn into his shell!", self->name);
}
Is there something I am missing? I have looked at a similar case here on stack overflow and my code looks identical at least in structure, so I am a bit confused. Thanks in advance!
p.s. if this is a linker error how do I get it to compile in an IDE without throwing an error?
When the compiler works on the main.c file, it knows that there is a structure named turtle_t but it knows nothing about it, it's not completely defined.
You need to make the structure "public", or at least the parts that are supposed to be public. This can easily be done by using two structures, one for the public "methods" and member variables, and another nested that contains the private data. Something like
typedef struct turtle_private_t turtle_private_t;
typedef struct turtle_t turtle_t;
struct turtle_t
{
turtle_private_t *private; // For private data
void (*hide)(turtle_t *self);
};
As an alternative, and one that is common, is that you don't place public functions in the structure, but instead use normal functions, with a special prefix to their name to indicate class. Something like
turtle_t *turtle_create(void); // Creates the turtle
void turtle_hide(turtle_t *); // Hides the turtle
You need to move your
typedef struct turtle_t
{
int numoflegs;
const char name[25];
void (*hide)(turtle_t *self);
} turtle_t;
from the .c file to the .h file. Incomplete type means, that the type is not known at compile type (it will be only known at link-time, if it's contained in a different translation unit). That means in your main.c turtle_t is only forward-declared and the structure itself is unknown - moving it to your .h file shall do the trick.

How to include struct variable declared in a header file in more than one source files?

I need a struct variable declared and defined in a header file to be accessible from more than one source files but I get a linker error. I'm putting small source code here. Linker error is
main.obj : error LNK2005: _a already defined in library.obj
fatal error LNK1169: one or more multiply defined symbols found
header.h
struct Student {
char *FirstName;
char *LastName;
};
struct Student a = {"John", "Jackson"};
library.c
#include <stdio.h>
#include "header.h"
void PrintStudentName(struct Student *name)
{
printf("%s\n%s\n", name->FirstName, name->LastName);
}
main.c
#include <stdio.h>
#include "header.h"
void PrintStudentName(struct Student *name);
int main()
{
PrintStudentName(&a);
return 0;
}
You should replace this definition line in the header
struct Student a = {"John", "Jackson"};
with this declaration:
extern struct Student a;
This declares a global variable of type struct Student.
Move the definition into one of the C files to complete the fix:
// This goes into one of the C files, does not matter which one.
struct Student a = {"John", "Jackson"};
Do not have definitions in a header file. These are solely meant to hold the declaration. The definition has to go into an implementation file (*.c). Think of the header file like the interface.
Disclaimer: I very well know ther might be exceptions to this rule. Also typedef is actually a definition, but one could just see it as an alias for the actual declaration (this is different from C++, btw).

how can I use a pointer to global struct in ansi-c?

Here is the case. In the file "fileA.c" I have
typedef struct MY_STRUCT
{
int A;
int B;
int C;
}MY_STRUCT;
MY_STRUCT Data;
/* Function */
int function(MY_STRUCT *params)
{
int varA, varB, varC;
varA = params->A;
varB = params->B;
varC = params->C;
}
And I need to fill the struct elements from other routine, for instance, "fileB.c" which contains the following:
extern MY_STRUCT Data;
int function(MY_STRUCT *params);
/* Function */
void userMain(void)
{
Data.A = 1254;
Data.B = 5426;
Data.C = 1236;
function(&Data);
}
But I'm getting the error:
"[Error] fileB.c E208: syntax error - token ";" inserted before "Data"
And whe I cross probe the error the compiler take me to the declaration "extern MY_STRUCT Data;"
So my question is how do I accomplish this functionality? I mean, how do I fill the elements of the structure from another function in another file different from the file where I declared the struct?
When the compiler is compiling fileB.c, it doesn't know about the typedef that you've defined in fileA.c. So in fileB.c, MY_STRUCT is an unknown type.
You should move the typedef to a common header, and include it in fileA.c and fileB.c.
Elaborating a bit on #pb2q answer:
Create a filea.h file with (omitting the defines and stuff):
struct MY_STRUCT
{
(blah blah blah ...)
};
extern MY_STRUCT Data;
This will declare the struct and tell whoever wants to know that the variable is declared in another file. Then put in filea.c the following lines
#include "filea.h" // near the top
(...)
MY_STRUCT Data; // Somewhere meaningful
This will actually declare the variable Data. Finally, in file "fileb.c" type
#include "filea.h"
that allows you to use the variable Data.

Simple header file visibility confusion in C

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).

Resources