Understanding structs in C - c

I just started learning C.
I have the following code:
#include <stdio.h>
void func(struct Foo foo){
foo.x =1;
foo.array[3] =2;
}
int main(){
struct Foo lol;
lol.x = 55;
lol.array[3] = 67;
func(lol);
printf("lol.x is %d and lol.array[3] is %d\n", lol.x, lol.array[3]);
return 0;
}
But when I compile it I get the following errors
structs.h:3:22: error: variable has incomplete type 'struct Foo'
void func(struct Foo foo){
structs.h:10:13: error: variable has incomplete type 'struct Foo'
struct Foo lol;
I looked it up and a lot of times the problem is in not defining structs in .h file. I defined it in a separate .h file, didnt help. I defined structs on the top of .c file, same errors.
I added this to the top of the file:
typedef struct Foo{
int x;
int array[3];
}Foo;
Can someone explain why its happening?

I looked it up and a lot of times the problem is in not defining structs in .h file. I defined it in a separate .h file, didnt help.
If you defined struct in separate .h file that you should include that file in this code.
#include <stdio.h>
#include "your_file.h"
....
From edit some other problem (UB)-
foo.array[3] =2; //you can't access index 3, declaration in struct is int array[3].

You are seeing a compilation time error, since struct Foo foo cannot evaluate the type. You have to declare the structure before using it.
You can include the header file or just write the following lines above func definition.
struct FOO
{
int x;
int array[n]; // n>3
};

Related

OOP and forward declaration of structure in C

I am studying C language and have recently learned how to write the OOP using C. Most part of it was not hard that much to understand for me except the name of structures type used to create new class.
My textbook used struct dummy_t for forward declaration and typedef struct {...} dummy_t for its definition. In my understanding, these are two different type because the former is struct dummy type and the later is struct type without a name tag but the sample code from the textbook worked well.
So I deliberately modified the sample code so that the difference in the names of structures will be much clearer. Below are the lines of code I tried.
//class.h
struct test_a;
struct test_a * test_init(void);
void test_print(struct test_a*);
//class.c
#include <stdio.h>
#include <stdlib.h>
typedef struct dummy{
int x;
int y;
} test_b;
test_b * test_init(void){
test_b * temp = (test_b *) malloc(sizeof(test_b));
temp->x = 10;
temp->y = 11;
return temp;
}
void test_print(test_b* obj){
printf("x: %d, y: %d\n", obj->x, obj->y);
}
//main.c
#include "class.h"
int main(void){
struct test_a * obj;
obj = test_init();
test_print(obj);
return 0;
}
// It printed "x: 10, y: 10"
As you can see, I used struct test_a for forward declaration and typedef struct dummy {...} test_b for definition.
I am wondering why I did not get the compile error and it worked.
I am wondering why I did not get the compile error
When you compile main.c the compiler is told via a forward declaration from class.h that there is a function with the signature struct test_a * test_init(void);
The compiler can't do anything other than just trusting that, i.e. no errors, no warnings can be issued.
When you compile class.c there is no forward declaration but only the function definition, i.e. no errors, no warnings.
It's always a good idea to include the .h file into the corresponding .c file. Had you had a #include "class.h" in class.c the compiler would have been able to detect the mismatch.
..and it worked
What happens is:
A pointer to test_b is assigned to a pointer to test_a variable
The variable is then passed as argument to a function expecting a pointer to test_b
So once you use the pointer it is used as it was created (i.e. as pointer to test_b). In between you just stored in a variable of another pointer type.
Is that ok? No
Storing a pointer to one type in a object defined for another pointer type is not ok. It's undefined behavior. In this case it "just happened to work". In real life it will "just happen to work" on most systems because most systems use the same pointer layout for all types. But according to the C standard it's undefined behavior.
It 'worked' because you did not include class.h in class.c. So the compiler can't see the implementation does not match the declaration.
The proper way is (but without the typedef for clarity):
// class.h
struct test_a;
struct test_a* test_init(void);
//class.c
#include "class.h"
struct test_a {
int x;
int y;
};
struct test_a* test_init(void)
{
...
}
The struct test_a in the header file makes the name test_a known to the compiler as being a struct. But as it does not now what is in the struct you can only use pointers to such a struct.
The members are defined in the implementation file and can only be used there.
If you want to use a typedef:
// header
typedef struct test_a_struct test_a;
test_a* test_init(void);
//implementation
struct test_a_struct {
int x;
int y;
};
test_a* test_init(void)
{
...
}

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

Forward declaration error I'm having trouble making sense of

Header file declaration:
typedef struct Queue *QueueP;
C File implementation:
struct Queue
{
char *head;
char *tail;
QueueItemT item; //char typedef from the header file, not what's giving error
int SizeL;
int sizeP;
int QueueSize;
};
C main file:
#include <stdio.h>
#include <stdlib.h>
#include "Queue1.h"
int main()
{
struct Queue queue;
QueueP myQueue = &queue;
return 0;
}
I am getting errors on the following lines with the following messages respectively:
struct Queue queue;
^
Main : variable has incomplete type 'struct Queue'
typedef struct Queue *QueueP;
^
Header : note: forward declaration of 'struct Queue'
Any idea what might be causing these errors? I'm new to working with multiple files and header files in C, so I'm really having trouble wrapping my head around these errors. Any help would be great, thanks!!
You put structure definition into a c file. This is not how it works: you need to put the definition into the header.
This is because a definition of a struct is not an implementation. C compiler needs this information in order to process declarations of the struct correctly. A forward declaration lets you define a pointer to your struct; declaring a struct itself requires a full definition.
If you would like to keep the details of your struct private, put it into a private header file. Include the public header file from your private header, too:
queue.h
typedef struct Queue *QueueP;
queue_def.h
#include "queue.h"
struct Queue
{
char *head;
char *tail;
QueueItemT item; //char typedef from the header file, not what's giving error
int SizeL;
int sizeP;
int QueueSize;
};
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "queue_def.h"
Now your project should compile without problems.
Actually, the reason I was getting forward declaration problems was because I was trying to access the struct (that was declared in the .c file) from within the main file.
Not only was this bad programming practice, the desired feature of the project was that the end user (i.e. the person using the interface and implementation to build their 'main.c' file) should have no idea what kind of struct was being used, they should simply be able to build a queue with the functions given and not know what was going on behind the scenes.
D'oh!!!

Dereferencing pointer to incomplete type C

Well, I'm getting this error and couldn't identify when i'm trying acess the fields.
In my bnum.c, i have the declaration of my struct:
#include "bnum.h"
struct num {
char *vet;
int tam;
};
And in my bnum.h, I have:
typedef struct num *b_num;
And in the main file I have:
#include"bnum.h"
int main(void){
b_num b;
b->tam = 5;
I'm using gcc on Linux Mint.
The main file does not have access to the structure definition, hence the error. You should move the definition
struct num {
char *vet;
int tam;
};
from .c to .h.
This is not a good-organized code.
The struct declaration should be in the header file, this way any src file that will include the header will be
familiar with that struct.

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.

Resources