extern vars and struct defined in other source file - c

Have two files with struct definitions. Header:
typedef struct _InputData InputData;
extern InputData input_data;
and source file:
struct _InputData{
char const*modification_l;
char const*amount_l;
char const*units_l;
};
InputData input_data = {...};
When i try to use input_data from other source file it gives me "invalid use of incomplete typedef ‘InputData’". I think i understand why it happened, but how i can deal with it in the gracefullest way.

You have do define the complete structure in the header file. Otherwise there is no way to know what fields it have, i.e. it's incomplete.

You can do this approach (more or less), but you need to define the struct as a pointer instead:
header
extern struct InputData* input_data;
source file:
struct InputData{
char const*modification_l;
char const*amount_l;
char const*units_l;
};
InputData* input_data;
...
input_data = malloc(sizeof(InputData));

You can use a pointer to a struct defined elsewhere, but not an instance. Compiler doesn't know what is the structure and how to calculate memory offsets for such a variable.
Why do you put the struct definition in the C file? put it in the header.

Related

Define extern variable of type alias in header in C

I have a C file that contains the following two declarations
struct mmap_table_entry_t {
uint32_t size;
uint64_t base_addr;
uint64_t length;
uint8_t type;
}* mmap_table_entry;
typedef struct mmap_table_entry_t* table_entries;
And I want to make the type table_entries extern in a header file. How do I do that without declaring the whole two above types?
BWT hiding pointers behind the pointers is not a very good idea.
typedef struct mmap_table_entry_t* table_entries;
table_entries is not a variable only type name. It cannot be extern.
extern table_entries table_entries_var;
I want to make the variable table_entries extern in a header file
If you want to declare your external var without defining the struct just do :
extern struct mmap_table_entry_t * table_entries;
If you want to define the type pointer to your struct your form typedef struct mmap_table_entry_t* table_entries; is valid.
A type cannot be extern. A typedef defines a type, it cannot 'force' a variable having that type to be extern. The type of a variable and its storage are two different things without link between them.

typedef struct in header file struct definition in c file

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.

Using static on typedef struct

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;

Passing pointers to private structs in C?

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.

How to declare a structure in a header that is to be used by multiple files in c?

If I have a source.c file with a struct:
struct a {
int i;
struct b {
int j;
}
};
How can this struct be used in another file (i.e. func.c)?
Should I create a new header file, declare the struct there and include that header in func.c?
Or should I define the whole struct in a header file and include that in both source.c and func.c? How can the struct be declared extern in both files?
Should I typedef it? If so, how?
if this structure is to be used by some other file func.c how to do it?
When a type is used in a file (i.e. func.c file), it must be visible. The very worst way to do it is copy paste it in each source file needed it.
The right way is putting it in an header file, and include this header file whenever needed.
shall we open a new header file and declare the structure there and include that header in the func.c?
This is the solution I like more, because it makes the code highly modular. I would code your struct as:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
I would put functions using this structure in the same header (the function that are "semantically" part of its "interface").
And usually, I could name the file after the structure name, and use that name again to choose the header guards defines.
If you need to declare a function using a pointer to the struct, you won't need the full struct definition. A simple forward declaration like:
struct a ;
Will be enough, and it decreases coupling.
or can we define the total structure in header file and include that in both source.c and func.c?
This is another way, easier somewhat, but less modular: Some code needing only your structure to work would still have to include all types.
In C++, this could lead to interesting complication, but this is out of topic (no C++ tag), so I won't elaborate.
then how to declare that structure as extern in both the files. ?
I fail to see the point, perhaps, but Greg Hewgill has a very good answer in his post How to declare a structure in a header that is to be used by multiple files in c?.
shall we typedef it then how?
If you are using C++, don't.
If you are using C, you should.
The reason being that C struct managing can be a pain: You have to declare the struct keyword everywhere it is used:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
While a typedef will enable you to write it without the struct keyword.
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
It is important you still keep a name for the struct. Writing:
typedef struct
{
/* etc. */
} MyStruct ;
will just create an anonymous struct with a typedef-ed name, and you won't be able to forward-declare it. So keep to the following format:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
Thus, you'll be able to use MyStruct everywhere you want to avoid adding the struct keyword, and still use MyStructTag when a typedef won't work (i.e. forward declaration)
Edit:
Corrected wrong assumption about C99 struct declaration, as rightfully remarked by Jonathan Leffler.
Edit 2018-06-01:
Craig Barnes reminds us in his comment that you don't need to keep separate names for the struct "tag" name and its "typedef" name, like I did above for the sake of clarity.
Indeed, the code above could well be written as:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, this is actually what C++ does with its simpler struct declaration, behind the scenes, to keep it compatible with C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
Back to C, I've seen both usages (separate names and same names), and none has drawbacks I know of, so using the same name makes reading simpler if you don't use C separate "namespaces" for structs and other symbols.
For a structure definition that is to be used across more than one source file, you should definitely put it in a header file. Then include that header file in any source file that needs the structure.
The extern declaration is not used for structure definitions, but is instead used for variable declarations (that is, some data value with a structure type that you have defined). If you want to use the same variable across more than one source file, declare it as extern in a header file like:
extern struct a myAValue;
Then, in one source file, define the actual variable:
struct a myAValue;
If you forget to do this or accidentally define it in two source files, the linker will let you know about this.
a.h:
#ifndef A_H
#define A_H
struct a {
int i;
struct b {
int j;
}
};
#endif
there you go, now you just need to include a.h to the files where you want to use this structure.

Resources