How can I pass around pointers to structs which have private definitions, without prepending the pointer types with struct?
For example this works:
typedef struct Handle {
Ino ino;
} Handle;
bool handle_open(Handle **);
But if I move the struct definition into a source file, other source files are forced to use struct Handle *, instead of Handle *.
You can typedef struct Handle Handle;. In this case, Handle is an incomplete type (just like struct Handle).
This should go fine in a header:
struct _Handle;
typedef struct _Handle Handle;
Then you can put the actual definition of _Handle in the body of the file that actually manipulates the struct.
if I move the struct definition into a source file, other source files are forced to use struct Handle *, instead of Handle *
Then typedef the pointer, instead of (or in addition to) the struct.
Related
I have two header files:
src/util/buffer.h:
//Namespace Src Util Buffer sub
struct sub_buffer{
size_t size;
void *buf;
};
//tons of static inline functions
src/lib_context.h:
//Namespace Src Lib Context slc
typedef struct sub_buffer slc_buffer; // Is this typedef ok?
struct slc_context{
//definition
};
void slc_set_buffer(slc_buffer *buf_ptr);
//tons of other structs and functions
The thing that I was not sure about was the typedef struct sub_buffer slc_buffer;. There was a choice to include the src/util/buffer.h, but that would intoroduce tightly coupling to the header and it would be more difficult to replace it with e.g. another buffer definition containing flexible array member.
Is it common to introduce such a typedef to the structure that is defined in another header file so its implementation will be provided in the c file when including the header (but not to include one header to another header file)?
No, that would be an error.
You probably meant
typedef struct sub_buffer slc_buffer;
in which case it's fine, you can always introduce typedef aliases to types, even without having those types defined in the scope you're in.
This is the reason the classical self-referencing "node" works:
typedef struct node node;
struct node {
node *next;
void *data;
};
Notice how on the first line a typedef for an unknown type is used.
I need some help to understand this struct:
typedef struct std_fifo{
char* name;
struct std_fifo* next;
}std_fifo, *fifo;
With typedef I know that I can use only std_fifo instead of writing struct std_fifo in my code. But what about the *fifo?
The code
typedef struct std_fifo{
char* name;
struct std_fifo* next;
}std_fifo, *fifo;
creates two (very badly named) typedef names, std_fifo and fifo.
The typedef name std_fifo is equivalent to the type struct std_fifo, and can be used in place of struct std_fifo:
std_fifo fifo_instance; // creates an instance of struct std_fifo
std_fifo get_fifo(); // declares get_fifo as a function returning an
// instance of struct std_fifo
void read_fifo( std_fifo * );// declares a function taking parameter of type
// pointer to struct std_fifo
The typedef name fifo is equivalent to the type struct std_fifo *, and can be used in place of struct std_fifo *:
fifo fifo_ptr; // creates a pointer to an instance of struct std_fifo
fifo get_fifoptr(); // declares get_fifoptr as a function returning a pointer
// to an instance of struct std_fifo
void read_fifo( fifo ); // declares a function taking a parameter of type
// struct std_fifo *
The reason code like
typdef struct std_fifo { ... } std_fifo;
works is because C has four different name spaces for identifiers: labels, tag names, struct and union member names, and everything else. The tag name std_fifo is always preceded by the struct keyword, which is how the compiler distinguishes it from the std_fifo typedef name.
Some advice on using typedefs:
While they can help your code scan better in some cases, using typedefs can actually obscure your intent and make types harder to use. If the user of the type has to be aware of its representation (such as to access a member of a struct, or dereference a pointer type, or to use the right conversion specifier in a printf or scanf call, or to call a function propertly, etc.), then you should not hide the representation behind a typedef.
If you decide you do want to hide a type's representation behind a typedef, then you should also provide a full API for any operations involving that type. C does this with the FILE type; instead of manipulating a FILE object directly, you pass a pointer to it to the various stdio routines. So, if you decide you want to hide struct std_fifo * behind the typedef name fifo, then you should also create an API like:
fifo new_fifo(); // create a new fifo queue
void destroy_fifo( fifo * ); // destroy an existing fifo queue
set_name( fifo, const char * ); // set the name of a fifo element
char *get_name( fifo ); // retrieve the name of a fifo element
fifo push_fifo( fifo ); // add an element to the end of the queue
fifo pop_fifo( fifo ); // remove an element from the front of the queue
Abstraction can be a Good Thing, but "leaky" abstractions are worse than no abstraction at all.
It is a valid definition of struct to give either with a name and with a pointer.
typedef struct std_fifo{
char* name;
struct std_fifo* next;
}std_fifo, *fifo;
In this code, where std_fifo is a struct and *fifo is the pointer to this struct.
I would strongly suggest you to take a look at here : http://www.cplusplus.com/forum/windows/57382/
I have a function that accepts void* as parameter, but I want to use it as if it's a struct.
typedef struct struct1
{
int val;
} struct2;
void func1(void* struct3)
{
printf("%d",struct3->val);
}
My purpose is for example, if I have a .h file where the function is defined as
typedef void* parameter1;
void func1(parameter1 p1);
And I wants to use the struct as a parameter in that function, without declaring the struct in the .h file.
Thanks for the answer printf("%d",((struct2 *)struct3)->val) mentioned by #i486, that's what I was looking for.
In the header, declare the structure type as an incomplete type. For example:
typedef struct struct1 struct1;
extern void func1(struct1 *p1);
Or:
struct struct1;
void func1(struct struct1 *p1);
You can mix'n'match extern or not and typedef vs struct tag.
In the implementation code (or implementation header if you have multiple source files implementing the support for the type), you include the public header and define the structure type:
struct struct1
{
…private details…
};
In C11 and beyond, you can repeat a typedef as long as it refers to the same type; in earlier versions of C, you could not do that.
The advantage of this approach is that the client code is forced to use your functions because they don't know the internals of the structure, but they get a measure of type safety. In particular, a random structure pointer can't be passed to this function. If everything takes void *, then you can pass a wrong structure type to the function because all void pointers look alike. That's both unkind and unnecessary.
We all know how to declare a structure in C:
struct Label1{ /* variables */ } Label2; // As I learned
But I want to know why this code works without declaring 'struct name':
typedef struct name s_name;
Or is in fact, does typing the code
struct name;
mean that I declared 'struct name' as a void structure or something like this?
Example of code:
typedef struct Data Data;
struct Data{ /*variables*/ };
If in the first line struct Data is declared as a void one, then in the second it's like I'm redeclaring it with members.
What is the explanation for this point?
Something like:
struct MyStruct;
Is called a forward reference. It creates an incomplete type and tells the compiler there will be a type of that name (and it's a struct - it works likewise for unions), and the details "follow later". Of such a type you cannot define variables, until you complete the type.
typedef struct MyStruct MyType;
Will just define the type name to be that struct. This is still an incomplete type.
However, you can take a pointer to an incomplete type:
MyType *my_t_pointer;
struct MyStruct *my_s_pointer;
This is useful for a struct to have pointers to objects of the same type when you provide the full declaration, "completing" the type:
struct MyStruct {
struct MyStruct *next;
};
Actually this is the only way to create nodes for lists, trees, and all other recursive data-structures. This is a major part of C programs (sometimes hidden).
Also, this mechanism is used to hide implementation details. Functions in the header need only know the struct exists to take/pass pointers to it. The use of these functions need not to know the details of the struct (but this way it cannot allocate it, so the module has to cover all aspects which need to know details on the struct). The full declaration is only inside the implementation file of the module.
These pointers are called "opaque" as one cannot "look through", i.e. access the fields of the struct as they are simply not known to it.
my_module.h:
struct MyStruct;
extern void my_init(struct MyStruct *obj);
my_module.c:
struct MyStruct {
int f1;
...
};
my_init(struct MyStruct *obj)
{
...
}
The typedef declares s_name as an alias for struct name so that you can declare variables, e.g.:
s_name *sptr;
The line
struct name;
declares that there is a struct type called name without defining its content. This is usually done in order to be able to declare variables as pointers to the struct type. You cannot declare variables of the actual struct type until it has been defined.
I use the following code a lot in C:
typedef struct
{
int member;
} structname;
Now i'm trying to keep that struct definition local to a particular source file, so that no other source file even knows the struct exists. I tried the following:
static typedef struct
{
int member;
} structname;
but GCC whines because of an illegal access specifier. Is it even possible to keep a struct's declaration private to a source file?
If you declare the typedef struct within a .c file, it will be private for that source file.
If you declare this typedef in a .h file, it will be accesible for all the .c files that include this header file.
Your statement:
static typedef struct
Is clearly illegal since you are neither declaring a variable nor defining a new type.
All declarations are always local to a particular translation unit in C. That's why you need to include headers in all source files that intend to use a given declaration.
If you want to restrict the use of your struct, either declare it in the file in which you use it, or create a special header that only your file includes.
A structure definition is private to a source file unless placed in a shared header file. No other source file can access the members of the struct, even if given a pointer to the struct (since the layout is not known in the other compilation unit).
If the struct needs to be used elsewhere, it must be used only as a pointer. Put a forward declaration of the form struct structname; typedef struct structname structname; in the headerfile, and use structname * everywhere else in your codebase. Then, since the structure members appear only in one source file, the structure's contents are effectively 'private' to that file.
Hernan Velasquez's answer is the correct answer: there are several problems with your code snippet. Here's a counter-example:
/* This should go in a .h if you will use this typedef in multiple .c files */
typedef struct {
int a;
char b[8];
} mystructdef;
int
main (int argc, char *argv[])
{
/* "static" is legal when you define the variable ...
... but *not* when you declare the typedef */
static mystructdef ms;