In my library, I have an instance structure, which contains everything needed for the library, this is so you can define multiple instances of the library. The library requires the user to define their own extension, or custom variables.
This is what I tried:
Library.h
typedef struct custom_s *custom;
typedef struct {
int a;
int b;
custom customs;
} instance;
And then the user can just do:
Main.c
// User sets their own custom structure
struct custom_s {
int c;
};
int main(void) {
instance test;
test.customs.c = 1;
}
However I get the error of "Segmentation fault".
Shouldn't it be:
test.customs->c = 1
Since you type'd it in
typedef struct custom_s *custom;
and Used as
custom in the instance structure.
Which is never allocated...
typedef struct custom_s *custom;
Defines a pointer to a custom struct. In your example this is an undefined pointer that is never allocated, so a segmentation fault occurs when you try to access it.
One side effect of opaque structures is that the size is unknown to client code. This means that you must create your own functions for allocating/creating them.
Make something like:
instance test;
test.customs = customs_create();
test.customs.c = 1;
Related
Context
We have three files:
module.h: it holds the declaration of a structure,
module.c: it holds the definition of the structure,
main.c: it holds an instance of the structure.
The goal is to use a structure in main.c by using an API (module.h) and not directly by manipulating the structure members. It is why the definition of the structure is in module.c and not in module.h.
Code
module.h
#ifndef MODULE_H
#define MODULE_H
typedef struct test_struct test_struct;
void initialize_test_struct(int a, int b, test_struct * test_struct_handler);
#endif
module.c
#include "module.h"
struct test_struct
{
int a;
int b;
};
void initialize_test_struct(int a, int b, test_struct * test_struct_handler)
{
test_struct_handler->a = a;
test_struct_handler->b = b;
}
main.c
#include "module.h"
int main(void)
{
test_struct my_struct; // <- GCC error here
test_struct * my_struct_handler = &my_struct;
initialize_test_struct(1, 2, my_struct_handler);
return 0;
}
Problem
If we compile those files with GCC, we will get the following error:
main.c:7:17: error: storage size of ‘my_struct’ isn’t known
Question
How can we force to use an API and so forbid to use directly a structure's members to manipulate a structure, the structure declaration and definition being in a different module than the main.c?
Since the definition of test_struct is not visible to your main function, you cannot create an instance of this object nor can you access its members. You can however create a pointer to it. So you need a function in module.c that allocates memory for an instance and returns a pointer to it. You'll also need functions to read the members.
In module.h:
test_struct *allocate_test_struct();
int get_a(test_struct *p);
int get_b(test_struct *p);
In module.c:
test_struct *allocate_test_struct()
{
test_struct *p = malloc(sizeof(test_struct));
if (!p) {
perror("malloc failed");
exit(1);
}
return p;
}
int get_a(test_struct *p)
{
return p->a;
}
int get_b(test_struct *p)
{
return p-b;
}
In main.c:
test_struct * my_struct_handler = allocate_test_struct()
initialize_test_struct(1, 2, my_struct_handler);
printf("%d\n", get_a(my_struct_handler));
printf("%d\n", get_b(my_struct_handler));
free(my_struct_handler);
You cannot instantiate a test_struct directly with only the include file because the details are not known when the C file is processed in the compiler. The language will only let you initialize pointers to objects of unknown size, not the objects themselves. The size and other details of test_struct are only known by the compiler when processing module.c
To get around this, you need to have module.c allocate data and provide a pointer to it in the initialize call. This means you have to either have the initialize function return a pointer to a newly created object (one that was either malloc'd or a global or static object), or have the function accept a test_struct **:
void initialize_test_struct(int a, int b, test_struct ** test_struct_handler)
{
*test_struct_handler = malloc(sizeof(test_struct));
//Do rest of init. You should also check return value of malloc
}
//Alternatively
test_struct * initialize_test_struct(int a, int b)
{
test_struct *temp;
temp = malloc(sizeof(test_struct);
//Init members as needed
return temp;
}
Normally in this situation the typedef is for a pointer to the opaque structure, and named to indicate that it's not the struct itself - 'typedef struct test_struct* test_struct_handle' could be appropriate, as the struct name itself is rather useless to users of the module (except to make pointers).
It's also good practice to:
Have accessor functions if you need them (which you do for your main file - see dbush's answer)
Have a 'de-init'/'free' function. The user does not necessarily know that malloc was used, and having a de-init function will make it possible to hide more implementation details.
First, what is it that you think clients of your library want to do that your API doesn’t support, and they’ll be tempted to manipulate the fields of your structure to accomplish? Consider extending the API.
One option is to force client code to get its structures from your factory function, rather than allocate them itself.
Another is to create a phony definition, perhaps containing only an array of char to establish a minimum size and alignment, so that the client code knows just enough to allocate an array of them, and the library module itself can cast the pointer and twiddle the bits.
Another is to put the definition in the header and add a comment saying that the fields are internal implementation details that might change.
Another is to port to an object-oriented language.
If we compile those files with GCC, we will get the following error:
main.c:7:17: error: storage size of ‘my_struct’ isn’t known
The reason why structures are inside the header files in the first place is so that the user source (here main.c) can access its members...
Your compiler does not know the address of the definition-less struct typedef struct test_struct test_struct; and so &my_struct won't give you its address!
And without an address, you can not get the size of any variable!
Explanation:
test_struct my_struct;
Here, you make a variable of an incomplete type and hence is not valid and doesn't have an address since its members are inaccessible...
test_struct * my_struct_handler = &my_struct;
And here you pass the address of my_struct which unnotably is not possible to gain (The structure is definition-less inside the header and the source is compiled so it can't be accessed either)...
So you use pointers in this case so that a temporary address can be assigned to the incomplete type:
/* Don't forget to change to
* 'void initialize_test_struct(int a, int b, test_struct ** test_struct_handler)'
* in the header file!
*/
void initialize_test_struct(int a, int b, test_struct ** test_struct_handler)
{
// Allocate an undefined address to the pointer...
*test_struct_handler = malloc(sizeof(test_struct));
(*test_struct_handler)->a = a;
(*test_struct_handler)->b = b;
}
// The declarations have to be present inside the headers as well...
// A function that returns the pointer to the variables a and b respectively...
// These functions can readily change their values while returning them...
int * get_a_ref(test_struct * test_struct_handler)
{
return &test_struct_handler->a;
}
int * get_b_ref(test_struct * test_struct_handler)
{
return &test_struct_handler->b;
}
and use it in main like this:
#include <stdio.h>
#include "module.h"
int main(void)
{
test_struct * my_struct_handler;
// Here a address is malloc'd to the pointer and the value is assigned to it...
initialize_test_struct(1, 2, &my_struct_handler);
// Will change the value of 'a' and similar for b as well...
// *get_a_ref(my_struct_handler) = 10;
printf("%d\n", *get_a_ref(my_struct_handler));
printf("%d\n", *get_b_ref(my_struct_handler));
return 0;
}
Just to remind you about the magic (and obscurity) of typedefs...
this error seems very easy to fix but i've been trying and have no clue.
So i have three files:
symtable.h:
typedef struct symbolTable *SymTable_T;
symtablelist.c:
#include "symtable.h"
struct Node{
char* key;
void* value;
struct Node* next;
};
struct symbolTable{
struct Node* head;
int length;
};
SymTable_T SymTable_new(void){
/* code */
}
And main.c:
#include "symtable.h"
int main(int argc, const char * argv[]) {
// insert code here...
SymTable_T emptyTable = SymTable_new();
emptyTable->length = 3; <------- ERROR
return 0;
}
I'm getting error: Incomplete definition of type "struct symbolTable"
Can anyone please give me a hint?
The reason i declare my struct in my source file is that i will have another implementation for the header file. so is there another way to fix my bug beside moving my struct declaration?
You can't access the members directly with an opaque pointer - if you keep the implementation in a separate source file, you'll have to access all the members via your interface, and not directly mess with the struct.
For instance, add this to symtable.h:
void SymTable_set_length(SymTable_T table, int len);
this to symtablelist.c:
void SymTable_set_length(SymTable_T table, int len)
{
table->length = len;
}
and in main.c change this:
emptyTable->length = 3;
to this:
SymTable_set_length(emptyTable, 3);
although in this specific case passing the length as an argument to SymTable_new() is an obviously superior solution. Even more superior is not letting the user set the length of a linked list data structure at all - the length is the number of items in it, and it is what it is. It would make no sense to, for instance, add three items to the list, and then allow main.c to set the length to 2. symtablelist.c can calculate and store the length privately, and main.c can find out what the length is, but it doesn't make much sense for main.c to be able to set the length directly. Indeed, the whole point of hiding the members of a struct behind an opaque pointer like this is precisely to prevent client code from being able to mess with the data like that and breaking the data structure's invariants in this manner.
If you want to access the members directly in main.c, then you have to have the struct definition visible, there is no alternative. This will mean either putting the struct definition in the header file (recommended) or duplicating it in main.c (highly unrecommended).
In typedef symbolTable *SymTable_T;, you refer to a non-existent type symbolTable. In C (unlike C++) the type is named struct symbolTable. (Note: the question has changed to fix this since answering it.)
There's a second problem. In main.c the code will need to be able to see the definition of struct symbolTable for you to be able to refer to fields of emptyTable. At the moment, the definition is hidden in a .c file... it should be moved to the header.
I'm working on a library for a user to use and manage with the function prototypes I provide within my header file. Now I have a working hashtable setup in manager.c but I'm at a loss at how to tackle this. I basically want to keep the hashtable "under the hood" from the user by providing them with
typedef struct Manager {
int size;
HashList **table;
} Manager;
so they can create this Manager object and use my provided functions to manipulate its contents. However, HashList is declared in my manager.c as
typedef struct HashList {
/*
* data stored here
*/
struct HashList *next;
} HashList;
Now obviously this will not compile as HashList must be in my header file since struct Manager uses HashList. But I do not want HashList to be in the header file as the user shouldn't explicitly have access to this as my functions manipulate the data stored at each hash.
Any advice?
If the user writes: Manager *m = ...;, is it expected that they'll ever write m->xyz? If not, then you don't need to expose the internals to the end user at all — it is sufficient to provide them with:
typedef struct Manager Manager;
If they must dereference the Manager type, it suffices to define:
typedef struct HashList HashList;
in the public header. They don't need to access the insides of that. (Well, if you've any pretensions to providing a concealed service, they have no need for that.)
Between the two options, option 1 is preferable. You provide functions that create and destroy the Manager type, and that allow the user to get or set the size of the structure. With the FILE * type, you don't write code that pokes inside the structure; you just use it via the interface functions you define. You should enforce the same discipline on the users of your code.
Note that if you allow the user to poke at the size element in the Manager structure, you can never tell when they changed it, so you've no idea whether your structure has been corrupted. If you have functional access to it (a get and a set function), you control what happens when the size changes.
You need to make your struct opaque. Keep the implementation details in the library .c files or a private header file and only provide a typedef only.
Example:
library.c
struct SomeStruct
{
int value;
};
struct SomeStruct *some_struct_alloc()
{
return malloc(sizeof(SomeStruct)));
}
void some_struct_set_value(struct SomeStruct *someStruct, int value)
{
if (someStruct != NULL)
someStruct->value = value;
}
int some_struct_value(struct SomeStruct *someStruct)
{
if (someStruct != NULL)
return someStruct->value;
return SOME_INVALID_VALUE_PERHAPS;
}
library.h
typedef struct SomeStruct SomeStruct;
SomeStruct *some_struct_alloc();
void some_struct_set_value(SomeStruct *someStruct, int value);
int some_struct_value(SomeStruct *someStruct);
program.c
#include <library.h>
int main()
{
SomeStruct *someStruct;
someStruct = some_struct_alloc();
if (someStruct == NULL)
return -1;
some_struct_set_value(someStruct, 3);
printf("%s\n", some_struct_value(someStruct));
free(someStruct);
return 0;
}
If the user tries to dereference the someStruct in main() then the compiler would halt with an error similar to dereferencing pointer of incomplete type.
In my opinion, this is a very good way to protect your library's data structure from being misused.
Isn't forward declaration, whether for structures or functions, supposed to do what forward declaration is expected to do, ie, to let us use the structure or function before they are defined? Why is the forward declaration of a structure not working in my code? And the main thing that just misses me, is forward declaration of structures of any use in C at all? When is it used? Can you please give me a small C program example to illustrate this?
My program gives the error error: storage size of 'x' isn't known|.
#include<stdio.h>
struct test;
int main(void)
{
struct test x;
printf("%zu",sizeof(x)); //Gives Error
//printf("%zu",sizeof(struct test));//This fails too
}
struct test
{
int a;
char b;
};
New Edit I tried to do what Carl Noum said,but even this is not working:
#include<stdio.h>
struct test;
void foo(struct test*);
int main(void)
{
struct test x={53,'x'},*ptr=&x;
foo(ptr);
}
void foo(struct test* p)
{
printf("%d,%c",p->a,p->b);
}
struct test
{
int a;
char b;
};
The compiler has to know the struct's layout when it compiles the main function.
A forward declaration is useful if you only have a pointer but not the actual type.
For example if you have a struct that contains a pointer to another struct
struct foo {
struct bar *b;
...
};
It is also essential if the bar also contain foo like
struct bar;
struct foo {
struct bar *b;
};
struct bar {
struct foo f;
};
In this case you have to have bar pre-declared.
A forward declaration usually means that you don't have to include .h file inside other .h file. This can speed up compilation significantly if the .h file is big.
Functions yes, structures no. struct test is an incomplete type where you use it.
A common use case for incomplete types is to declare an opaque type. In a header file, you declare:
struct test;
And then some API that uses struct test only via pointers:
int func1(struct test *);
struct test *func2(void);
In the accompanying implementation, you include the full declaration so that your functions know what to do with the structure:
struct test
{
int a;
char b;
};
void func1(struct test *t)
{
return t->a;
}
Edit:
Your new code doesn't do anything differently - you're still trying to operate on an incomplete type, and you still can't do that. In particular, this declaration:
struct test x = {53,'x'};
Can't work if struct test is an incomplete type. You can (generally) only use pointers to an incomplete type. In this case, that might mean creating a function that allocates and returns a pointer to a new structure, rather than trying to declare and initialize one on the stack.
Struct type declared by a forward declaration (i.e. an incomplete type) can be used only in a limited number of ways. Applying sizeof to such a truct type is not one of them. On top of that, you can't use incomplete types in object definitions and you cannot access data fields of incomplete struct types.
In other words, sizeof requires a complete type. Your forward-declared struct type is not a complete type. Operator -> also requres a complete type of the left-hand side. Object definition (like struct test x) also requires a complete type.
In the question Why should we typedef a struct so often in C?, unwind answered that:
In this latter case, you cannot return
the Point by value, since its
declaration is hidden from users of
the header file. This is a technique
used widely in GTK+, for instance.
How is declaration hiding accomplished? Why can't I return the Point by value?
ADD:
I understood why I can't return the struct by value, but, is still hard to see why i can't deference this point in my function. i.e. If my struct have member named y, why i can't do it?
pointer_to_struct->y = some_value;
Why should I use methods to do it? (Like Gtk+)
Thanks guys, and sorry for my bad english again.
Have a look at this example of a library, using a public header file, a private header file and an implementation file.
In file public.h:
struct Point;
struct Point* getSomePoint();
In file private.h:
struct Point
{
int x;
int y;
}
In file private.c:
struct Point* getSomePoint()
{
/* ... */
}
If you compile these three files into a library, you only give public.h and the library object file to the consumer of the library.
getSomePoint has to return a pointer to Point, because public.h does not define the size of Point, only that is a struct and that it exists. Consumers of the library can use pointers to Point, but can not access the members or copy it around, because they do not know the size of the structure.
Regarding your further question:
You can not dereference because the program using the library does only have the information from private.h, that does not contain the member declarations. It therefore can not access the members of the point structure.
You can see this as the encapsulation feature of C, just like you would declare the data members of a C++ class as private.
What he means is that you cannot return the struct by-value in the header, because for that, the struct must be completely declared. But that happens in the C file (the declaration that makes X a complete type is "hidden" in the C file, and not exposed into the header), in his example. The following declares only an incomplete type, if that's the first declaration of the struct
struct X;
Then, you can declare the function
struct X f(void);
But you cannot define the function, because you cannot create a variable of that type, and much less so return it (its size is not known).
struct X f(void) { // <- error here
// ...
}
The error happens because "x" is still incomplete. Now, if you only include the header with the incomplete declaration in it, then you cannot call that function, because the expression of the function call would yield an incomplete type, which is forbidden to happen.
If you were to provide a declaration of the complete type struct X in between, it would be valid
struct X;
struct X f(void);
// ...
struct X { int data; };
struct X f(void) { // valid now: struct X is a complete type
// ...
}
This would apply to the way using typedef too: They both name the same, (possibly incomplete) type. One time using an ordinary identifier X, and another time using a tag struct X.
In the header file:
typedef struct _point * Point;
After the compiler sees this it knows:
There is a struct called _point.
There is a pointer type Point that can refer to a struct _point.
The compiler does not know:
What the struct _point looks like.
What members struct _point contains.
How big struct _point is.
Not only does the compiler not know it - we as programmers don't know it either. This means we can't write code that depends on those properties of struct _point, which means that our code may be more portable.
Given the above code, you can write functions like:
Point f() {
....
}
because Point is a pointer and struct pointers are all the same size and the compiler doesn't need to know anything else about them. But you can't write a function that returns by value:
struct _point f() {
....
}
because the compiler does not know anything about struct _point, specifically its size, which it needs in order to construct the return value.
Thus, we can only refer to struct _point via the Point type, which is really a pointer. This is why Standard C has types like FILE, which can only be accessed via a pointer - you can't create a FILE structure instance in your code.
Old question, better answer:
In Header File:
typedef struct _Point Point;
In C File:
struct _Point
{
int X;
int Y;
};
What that post means is: If you see the header
typedef struct _Point Point;
Point * point_new(int x, int y);
then you don't know the implementation details of Point.
As an alternative to using opaque pointers (as others have mentioned), you can instead return an opaque bag of bytes if you want to avoid using heap memory:
// In public.h:
struct Point
{
uint8_t data[SIZEOF_POINT]; // make sure this size is correct!
};
void MakePoint(struct Point *p);
// In private.h:
struct Point
{
int x, y, z;
};
void MakePoint(struct Point *p);
// In private.c:
void MakePoint(struct Point *p)
{
p->x = 1;
p->y = 2;
p->z = 3;
}
Then, you can create instances of the struct on the stack in client code, but the client doesn't know what's in it -- all it knows is that it's a blob of bytes with a given size. Of course, it can still access the data if it can guess the offsets and data types of the members, but then again you have the same problem with opaque pointers (though clients don't know the object size in that case).
For example, the various structs used in the pthreads library use structs of opaque bytes for types like pthread_t, pthread_cond_t, etc. -- you can still create instances of those on the stack (and you usually do), but you have no idea what's in them. Just take a peek into your /usr/include/pthreads.h and the various files it includes.