I'm trying to figure out how exactly forward declarations interact. When forward declaring a function that takes a typedef'd struct, is there a way to just get the compiler to accept a previously forward declared (but not actually defined) struct as a parameter?
The code that I've got working:
typedef struct{
int year;
char make[STR_SIZE];
char model[STR_SIZE];
char color[STR_SIZE];
float engineSize;
}automobileType;
void printCarDeets(automobileType *);
What I wish I could do:
struct automobileType;
void printCarDeets(automobileType *);
//Defining both the struct (with typedef) and the function later
I feel like I'm either missing something really basic or not understanding how the compiler deals with forward declarations of structs.
Typedefs and struct names are in different namespaces. So struct automobileType and automobileType are not the same thing.
You need to give your anonymous struct a tag name in order to do this.
The definition in your .c file:
typedef struct automobileType{
int year;
char make[STR_SIZE];
char model[STR_SIZE];
char color[STR_SIZE];
float engineSize;
}automobileType;
The declaration in your header file:
typedef struct automobileType automobileType;
void printCarDeets(automobileType *);
Related
I have a problem with some of my functions. I want to get a member ob a struct, out of another struct. The normal call is functionel, but embedded in a function, it doesn't work. Is there any idea why and how I can solve that?
The following function is an example. It should get the time out of a struct, embedded in another struct via the time-converting function "FUN_1"
FUN_1((time_t *)&ptr_to_s_20b_parse_entries->s_28b_meta->time_c);
My structs are:
struct s_28b_meta {
int version;
__time32_t time_c;
__time32_t time_m;
uint32_t i_next;
int hash_value;
int len_database_name;
int *ptr_database_name;
};
struct s_20b_parse_entries {
int *s_28b_meta;
int *s_8b_keys;
int **a_db_entries;
size_t n_db_entries;
int i_next;
};
The decleration:
struct s_28b_meta *ptr_temp;
struct s_20b_parse_entries *ptr_to_s_20b_parse_entries;
In struct s_20b_parse_entries, you have the s_28b_meta field defined as int *. This is not a pointer to struct so you can't use the -> operator on it, which is why you're getting the error.
It should be defined as a struct s_28b_meta *.
Hi I was triying to make something like this, but I cant sort it out. The problem is one typedef needs the other one. I would really appreciate someones help!
#ifndef SHELL_DATA_H
#define SHELL_DATA_H
#include <buffer.h>
#define COMMANDS 10
#define MAX_ARGS 4
typedef struct {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
} t_command;
typedef struct {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
} t_shellData;
#endif
typedef struct command t_command;
typedef struct shelldata t_shellData;
struct command {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
};
struct shelldata {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
};
should fix it up for you. The structure tag and typedef name can be the same; I just renamed them for clarity.
C is a simple language, with an underlying principle of do not surprise people. For this reason, entities in C need to be declared or defined before they are used. As a simple example:
int f() {
int a = 7;
int b = a;
....
}
is OK, but this is not:
int f() {
int b = a;
int a = 7;
....
}
and while not exactly, languages like golang permit this -- the compiler will root around and find the definition you obviously wanted.
Typedef, in C, really just puts an entry into the symbol table; it is like a define, but less blunt, so the line:
typedef struct a A;
Serves to inform the compiler of two things: somewhere there is a structure with tag a, and I want A to be a shortform for it. There is another form of this:
struct a;
typedef struct a A;
Here, the first line tells the compiler "I want you to know about a thing called struct a"; and the second line "I want an alias to that struct a thing called A".
So, as the compiler progresses through the source, it knows that an A means a struct a, and even if it hasn't seen the definition of struct a, it has a placeholder.
But, if you attempted, before defining struct a to define another structure:
struct b {
struct a stuff;
int morestuff;
};
The compiler would complain, because it doesn't know the layout of a struct a; however this:
struct b {
struct a *stuff;
int morestuff;
};
is OK, because it knows how big a pointer is, and can defer its understanding of a struct a until it needs it.
So, Summary: declare or define data types before you attempt to use them. The C compiler requires it. A declaration is ok, unless you need the actual layout of it, in which case a definition is required.
Good Luck.
I've the question about typedef statement.
Here is the code how i always write this statement:
typedef struct name
{
}name_t;
And here is the another example how i can write that:
typedef struct
{
}name;
Question is: what is purpose of that ways?
You need to use the first format if you have to refer to the type before the typedef is completed. This is necessary if the structure contains a pointer to the same type. This comes up when defining linked lists.
typedef struct name
{
int value;
struct name *next;
}name_t
You can't use name_t *next; inside the structure declaraction, because name_t isn't defined until later.
typedef struct name
{
}name_t;
name here is a struct tag and superfluous for the normal use-case, since you end up with a typedef anyhow and should only use name_t in your code from there on.
The only reason you'd add a tag there is the special case where you need a self-referencing struct such as a struct name* next; member in a linked list or such. In such cases we have to use the struct tag since the typedef name cannot be used before the typedef statement itself is done. Another alternative to that is to forward declare the struct.
The _t naming is industry standard way of naming types since the dawn of time. Unfortunately, the POSIX standard had the misguided idea to disallow such naming, so if you care about POSIX compliance, you should not name your types with _t in the end. If you don't care about POSIX, you should use _t because it gives proper, self-documenting code.
typedef struct name
{
int a;
double b;
char c;
}name_t;
name is a structure tag while name_t is a new type created by typedef.
To provide a structure tag explicitly is useful, if:
You want to implement a forward-declaration of the structure for use it in f.e. function definitions or other structures before the structure definition occurs (important if you have several translation units/C files).
For example:
File1.c
struct name; // forward declaration of structure `name`.
void foo(struct name *ptr)
{
....
}
struct bar
{
int x;
struct name y;
}
File2.c
typedef struct name
{
int a;
double b;
char c;
}name_t;
You want to define a pointer to an object of the structure itself inside of the structure, like required by linked lists:
typedef struct name
{
int a;
double b;
char c;
struct name *next;
}name_t;
I try to do this in C :
typedef struct s_match_fptr
{
char *str;
int (*funcptr)(t_client *client, char **command);
} t_match_fptr;
typedef struct s_client
{
int socket_fd;
int port;
char *server_ip;
struct sockaddr_in s_in;
t_match_fptr *db;
} t_client;
The point is I try to declare a function pointer that takes in parameter a t_client struct in my t_match_ptr struct.
Also, my struct t_client have an array of t_match_ptr.
For simplify, A need to be declared after B AND B needs to be declared after A.
So, is there a way to "predeclare" t_client before the declaration of t_match_ptr?
Thank you and sorry for bad english.
Forward declaration.
Add at the beginning: typedef struct s_client t_client;
Now the compiler will know the type t_client when encountered in s_match_fptr.
Note, the type must be used only by reference in the s_match_fptr definition (i.e. using a pointer). This way the compiler doesn't need to know the actual contents of the type when parsing the code.
I have a typedef for a struct in sampleHeader.h that is similar to:
typedef struct example Example;
and I have in my sampleSource.c:
struct example{
char a[4];
char b[4];
char c[5];
}
Now for some reason when I return a pointer back to my main function which references a struct that has been created ( and malloc'd) and try to print out the values of each member I get an error along the lines of "cannot derefence incomplete type"
Any ideas?
In the header file you have only forward declared the struct. That's fine and you'll be able to declare pointers and references to the struct in the header (and any other header or cpp file that includes this header too).
As the compiler has only seen the definition in the cpp module, this is the only place that you'll be able to declare variables of type struct example by value or to dereference pointers to access members. Outside of the cpp file the compiler doesn't know how big the struct is or what is members are.
If you need to use the struct in multiple modules declare and define the struct together in the header.
Hard to say for sure without seeing the actual code, but....
struct example{
char a[4];
char b[4];
char c[5];
};
^ note the new semi colon.