Struct declared in C header file - gcc malloc error - c

I have declared a typedef struct on header files as follows:
myheader.h
typedef struct mystruct mystruct;
myheader.c
typedef struct mystruct{
double *ptr1;
double *ptr2;
int *ptr3;
mystruct *ptr4;
mystruct *ptr5;
}mystruct;
program.c
#include "myheader.h"
int main()
{
mystruct *A = (mystruct *)malloc(sizeof(mystruct));
}
when i try to compile using:
gcc -o myprogram myprogram.c myheader.c
i get the following error:
error: invalid application of ‘sizeof’ to incomplete type ‘mystruct’ {aka ‘struct mystruct’}
mystruct * A = (mystruct *)malloc(sizeof(mystruct));
Is there something wrong with my code or am I compiling in the wrong way?

As #someprogrammerdude has already pointed out in his comment about translation units: when the compiler compiles main.c it has only knowledge about main.c and the included headers. So all it knows is that that there is a struct typedefed as mystruct but it knows nothing about its content and thus cannot determine ts size either, so you cannot use sizeof(). For the same reason you couldn't access any struct members, int *p = mystruct->ptr3; or mystruct->ptr1 = &mydouble; wouldn't compile as well.
Nevertheless that design is quite common. Let's assume you want to encapsulate every access to mystruct in an OO like manner. Then you have a source, say mystruct.c where you actually define the structure (like you did in myheader.c) and provide all neccessary getter and setter functions (including an allocation function). Then in every other source you could pass struct pointers any way you like but for everything else you have to use the designated functions.
The advantage of that approach is that in the future you're free to modify the struct whithout having to recompile every source that uses it.

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

Why is it valid to define a type as pointer to an undefined struct in C?

I was digging into a 3rd party code base and found that it is apparently valid to declare a type as a pointer to an undefined struct. As a minimum working example, consider a C file test.c containing nothing but:
typedef struct foo *bar;
What surprises me is that this file compiles without any problems using the command
gcc test.c -shared
Why does the compiler not complain about the struct foo not being declared anywhere?
My environment is Ubuntu 16.04 with gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609.
The declaration above creates a forward declaration of struct foo. Although you can't access its members, you can operate on a pointer to it.
This is commonly referred to as an opaque type, and is used to hide implementation details of a library from users of the library.
For example a library implementation may contain the following:
lib.c:
struct foo {
int f1;
};
struct foo *init()
{
return malloc(sizeof(struct foo));
}
void set1(struct foo *p, int val)
{
p->f1 = val;
}
int get1(struct foo *p)
{
return p->f1;
}
void cleanup(struct foo *p)
{
free(p);
}
The header file for this library might look like this:
lib.h:
struct foo;
struct foo *init(void);
void set1(struct foo *p, int val);
int get1(struct foo *p);
void cleanup(struct foo *p);
The user of this library would use the init function to create an instance of the struct and the set1 and get1 functions to read / update the member. The user can't however create an instance of struct foo or access the members without going through one of the interface functions.
Because pointer to structs have same size (for any structs). The size of a structure pointer doesn't depend on it's definition. Because no matter what, the pointer to it would be behaved the same way as any other structures pointer.

Using a void* as an argument inside a function pointer inside a structure definition causes a syntax error

I am creating an interface structure
typedef struct Circular_Buffer_Interface_t * Circular_Buffer_Interface;
typedef struct Circular_Buffer_Interface_t {
U8 (*Put)(Circular_Buffer, void*);
U8 (*Get)(Circular_Buffer, void*);
U8 (*Reset)(Circular_Buffer);
BOOL (*isFull)(Circular_Buffer);
BOOL (*isEmpty)(Circular_Buffer);
} Circular_Buffer_Interface_t;
typedef struct Circular_Buffer_t * Circular_Buffer;
typedef struct Circular_Buffer_t {
Circular_Buffer_Interface Interface;
} Circular_Buffer_t;
My question is when I try to compile why using void* as a function argument it throws a syntax error.
if I use a typedef
typedef void* VoidPtr
and then use
typedef void* VoidPtr;
typedef struct Circular_Buffer_Interface_t {
U8 (*Put)(Circular_Buffer, VoidPtr);
U8 (*Get)(Circular_Buffer, VoidPtr);
U8 (*Reset)(Circular_Buffer);
BOOL (*isFull)(Circular_Buffer);
BOOL (*isEmpty)(Circular_Buffer);
} Circular_Buffer_Interface_t;
everything complies just fine.
Does anyone have a clue while this is happening?
Thanks in advance.
This member declaration
U8 (*Put)(Circular_Buffer, VoidPtr);
will work fine if neither Circular_Buffer nor VoidPtr are defined with typedef at that point in the source code. (U8 must be defined, though.) That's because it will be accepted as a K&R-style function declaration which specifies the names of the parameters but not their types. (That is, Put will be declared as a pointer to a function taking two parameters of unspecified type.)
It will also work if both Circular_Buffer and VoidPtr are defined as typedefs, in which case it will be treated as a normal standard C declaration.
If you compile with -Wall, the first case will probably produce a warning. -Wall is always recommended.
It should fail to compile if only one of the two identifiers is declared as a typedef, so I don't know how it works in the case where typedef void* VoidPtr comes before the member declaration, and typedef struct ... Circular_Buffer comes afterwards. Perhaps that's an obscure feature of an old version of gcc. (Once the compiler decides it is a K&R function declaration, the actual parameter names can be ignored unless the it is a function definition, and in the context in which the line appears, it cannot be a function definition.)
The first declaration, with the void *, seems perfectly valid C. I added some code to make this a complete program:
#include <stdio.h>
typedef int U8;
typedef int BOOL;
typedef int Circular_Buffer;
typedef struct Circular_Buffer_Interface_t {
U8 (*Put)(Circular_Buffer, void*);
U8 (*Get)(Circular_Buffer, void*);
U8 (*Reset)(Circular_Buffer);
BOOL (*isFull)(Circular_Buffer);
BOOL (*isEmpty)(Circular_Buffer);
} Circular_Buffer_Interface_t;
int main() {
puts("hello");
}
This program compiles successfully and without warning with GNU C version 5.2 on MacOSX:
> gcc-5 -std=c99 -Wall x.c
> ./a.out
hello
The same works with the Apple version of clang. Thus I suspect that the problem is with your C compiler, rather than with your code.

errors while trying to pass a structure to a function

In the following program I try to pass a structure to a function. But I get errors,and I do not understand why. What mistake have I made in this program ?
I am using gcc for compiling this c program.
#include <stdio.h>
struct tester {
int x;
int *ptr;
};
void function(tester t);
int main() {
tester t;
t.x = 10;
t.ptr = & t.x;
function(t);
}
void function(tester t) {
printf("%d\n%p\n",t.x,t.ptr);
}
Errors :
gcc tester.c -o tester
tester.c:8:15: error: unknown type name ‘tester’
tester.c: In function ‘main’:
tester.c:12:2: error: unknown type name ‘tester’
tester.c:13:3: error: request for member ‘x’ in something not a structure or union
tester.c:14:3: error: request for member ‘ptr’ in something not a structure or union
tester.c:14:13: error: request for member ‘x’ in something not a structure or union
tester.c: At top level:
tester.c:18:15: error: unknown type name ‘tester’
NOTE : If I replace printf with cout and stdio with iostream and name the extension to .cpp (!), I get no errors. Why is that ? No wonder I compile it using g++
If you don't typedef the struct you must specify struct in front of the struct name while declaring it like so:
struct tester t;
Either you do that or you do the following:
typedef struct {
int x;
int *ptr;
}tester;
Update
Below is a quote from Adam Rosenfield from the following post Difference between 'struct' and 'typedef struct' in C++?:
In C++, all struct/union/enum/class declarations act like they are implicitly typedef'ed, as long as the name is not hidden by another declaration with the same name.
your struct isn't named. either use struct tester t; or usa a typedef
The thing is you're trying to compile with gcc, which is a "c language" compiler and you're following C++ style of code.
It is possible to create a struct variable by just structname variablename;
but in c++, you explicitly have to tell the compiler it is a struct like
struct structname variablename;
Just do that and you'll be fine, otherwise you can use a typedef which is basically you tell the compiler form now on you are going to call struct tester to only tester, which will suit you more since you only have to only a minor change.

Error: In C, got the error "dereferencing pointer to incomplete type" in a struct pointer

Hello Everybody!
I got the following error, while trying to test a code for the game Clever Frog:
error: dereferencing pointer to incomplete type
The 'full code' is at pastebin.com - here (won't expire). But I think that with the explanation below, anybody can understands. Note: I haven't implemented yet the function that will erase the allocated memory and other things.
I have a struct defined in a 1.c file:
#include "1.h"
...
struct test {
int a;
};
...
I have a 1.h wicth have the typedef using it:
...
typedef struct test testT;
...
Then I have a function that has a parameter in it depending on testT, wich is in 2.c:
...
void funcTest(testT **t, int *size, ..){
/* another function that creates mem.space/alocate memory based enter code here`on the need of size above */
createMem(t,*size); /* void createMem(testT **t, int size); */
t[0]->a = 0; /*ERROR HERE*/
/* ... more code ... */
}
...
The 2.h file is like this:
...
void funcTest(testT **t, int *size, ..);
...
I will pass a testT *var as the way below, at the main programam:
...
testT *varTest; int size;
funcTest(&varTest, &size);
...
The bizarre thing is that the code compile when I use struct test at 1.h file (removing struct test from 1.c - which is wrong). But, when running the compiled program, exactly where the error occurs is the place of t[0]->a.
I already tried 'everything' but nothing worked :( I have faith that is something very stupid, so if anybody knows something, please tell me :D
Thanks!
When you try to access the a member of the t[0] struct the compiler needs to know how this struct looks like (for example to see if there even is any a member in it). Since you didn't put the struct test type definition anywhere where the compiler can see it when compiling 2.c, you get an error. The compiler doesn't know what a struct test contains.
If you put the definition of the struct test in 1.h, the compiler sees how that type looks like and can use the struct members.
Just put the complete type definition in 1.h, that's where it's supposed to be.
Somewhere you have a preprocessed file that has
typedef struct test testT;
Which doesn't include
struct test {
int a;
};
Preprocessing inlines all the #includes directives. As long as you were only using a testT pointer, the compiler would have known to "allocate a pointer's worth of memory" and the compilation would have progressed further than expected.
When you actually try to use that pointer to dereference something, the compiler would then realize it NEEDED the full definition of "struct test" and you would get the error displayed.
If you want the struct to be usable both in 1.c and 2.c, it must be defined in a header file that is visible to both. I don't know why you say that this is "wrong", it's common practice and AFAIK there is no other way around that directly.
If it's only defined in 1.c, then the compiler has no idea if struct test has a member named "a" when processing 2.c.
Another option is to just keep the forward declaration as you have now, but also include accessor/mutator functions in the header. Then 2.c does not have to know about the "internals" of struct test, but can act on it. This is also very common in C APIs.
(You could also define the struct identically both in 1.c and 2.c but that's a very bad idea.)
The definition of struct Test is only visible inside the file 1.c. The code t[0]->a doesn't see that this struct has a member named a. The types shared between several compile units shuld be defined in a header!
You should know that C/C++ compiles each .c file separately, so it has no way to know that the structure is defined in some other .c file.
You should perhaps do the following:
(1.h)
struct test {
int a;
};
...
(1.c)
#include "1.h"
...
(2.c)
#include "1.h"
...
void funcTest(testT **t, int *size, ..){
createMem(t,*size); /* void createMem(testT **t, int size); */
t[0]->a = 0;
/* ... more code ... */
}
But, when running the compiled program, exactly where the error occurs is the place of t[0]->a.
The pointer to the allocated memory is actually in *t, not t (as seen from your createMatrix code at Pastebin), so you should really be doing:
(*t)[0].a
and similarly in your for loop:
(*matriz)[i].row

Resources