Declaring a structure in a header file - c

I want to declare a structure in a header file. When I declare a simple variable in a header file I simply specify the variable as external like this.
The variable in the .c file:
int var;
And the same variable presented in the header file:
extern int var;
So far so good. But what about a struct? If I have the following struct in my .c file
typedef struct
{
unsigned char seconds;
unsigned char minutes;
unsigned char hours;
unsigned char day;
unsigned char month;
union
{
unsigned int year;
unsigned char year_byte[2];
}year_vars;
}time;
How do I declare the structure in the header file?

Declaring a global variable is not the same thing as declaring a type. If the typedef should be visible to everyone that includes your h file, then naturally the typedef needs to be in the h file.
And the other way around: if the typedef is local to your C file, there is no need to present it to the caller at all.
Please note that there is never a reason to use global non-constant variables in C. Replace them with static file scope variables in your C file, that are accessed through setter/getter functions.

Into the .h go:
Definitions of all types to be used for externally visible variables
All extern declarations of variables (thus externally visible variables)
Into the .c go:
Definitions of all types to be used by internal-only visible variables
Definitions of all variables (visible externally and internally)

Type definitions should go in the header only. They do not need to be repeated in the .c files. Simply include the header in your source files to access the type definitions.
time.h
typedef struct
{
...
} time;
time.c
#include "time.h"

Related

structure extern with different type

I found the below warning in map file , the struct extern declaration TYPE got changed in file2.c declaration. Below warning from IAR compiler,
Please let me know what is the impact of below type cast.
what is the memory size in file2.c while link time ?
I am trying to find impacts of this implementation not the solution
"struct_tag" to "uint8"
Warning[w6]: Type conflict for external/entry "Block_01", in module file2.c against external/entry in module file1.c; different basic types
/* In module file2.c: */
uint8 NvM_Block_01;
typedef unsigned char uint8;
/* In module file1.c: */
Block_01_T Block_01;
typedef struct Block_01_Tag Block_01_T;
typedef struct Block_01_Tag
{/* 4 bytes with CRC16 */
uint16 Data_01;
uint16 Crc_01;
}Block_01_T;
File1.c
Block_01_T Block_01 = {1234,1};
File2.c
extern unsigned char Block_01;
#define RPM_BLOCK (&Block_01)
Thanks
Damodaran
In file2.c, Block_01 is given type unsigned char, which is 1 byte in size. This will access the first byte of the structure Block_01_t, which will be part of Block_01_T.Data_01.
You have two variables of the same name. Block_01 and different types. This is not allowed. You need to change one of them.
Block_01_T Block_01 = {1234,1}; // in File1.c
extern unsigned char Block_01; // in File2.c
If you want both files to refer to the same variable, you can use.
extern Block_01_T Block_01; // in File2.c
The linker generally doesn't care about the size of object, just their addresses. The compiler reserves space in the object file that defines the object. In this case, the definition is in File1.c, which declares a structure containing two uint16, so it will most reserve at least 4 bytes.
According to the C standard, the consequences are undefined when you use Block_01 in File2.. But I think it's likely that it will be equivalent to giving it the same structure type declaration, and then using *(char *)(&Block_01).

C variable definition vs extern decleration

This seems like the sort of question that has already been covered but I can't seem to find out where.
I have come across a peculiar behaviour of gcc.
I file A I have the following definition:
struct SomeStruct {
unsigned int uiVarA;
unsigned int uiVarB;
} SomeVar;
I file B the extern decleration differs:
extern struct SomeStruct {
unsigned char filler;
unsigned int uiVarA;
unsigned int uiVarB;
} SomeVar;
In fact I can make the definition be a double and the extern decleration be an int and gcc will happily compile without so much as a warning (with -Wall and -Wextra even).
I can only conclude this must mean it is perfectly legal behaviour but how it that so?
I am aware that the linker does the job of mapping the two variables but is there no errorchecking at this stage?
Unless you include one file in the other, the compiler will not see both of your definitions.
Normally you would simply declare the struct in a header file separately and then declare variables of that type, so like:
in a.h:
struct SomeStruct {
unsigned int uiVarA;
unsigned int uiVarB;
}
In a.c you could then do: struct SomeStruct SomeVar; and in b.c extern struct SomeStruct SomeVar after including a.h. Or better yet, put the extern struct in a header file and include that in both a.c and b.c.
From the C Spec.
6.2.7 Compatible type and composite type
2 All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undeļ¬ned.
So, it is not perfectly legal behavior in that the behavior is undefined. But that doesn't mean that your linker has the ability to check for it. It is syntactically correct (as long as each declaration is in different translation units).

Advantages of using extern after the declaration of fucntion pointer in the same header file

In the code below, can it be expained why extern has been used right after the declaration on function pointer.
myfuncs.h
typedef void (*initMyfuncs_t)(Init_t*, CallBacks_t *,result_t*);
extern initMyfuncs_t _initMyfuncs;
and we are using it in myfunc.c file
void *glbfuncs=NULL
glbfuncs = dlopen("glbfuncs.so",RTLD_NOW);
initMyfuncs_t _initMyfuncs=NULL;
_initMyfuncs = dlsym(glbfuncs, "_initMyfuncs");
Usually,we use extern in the files or other header file where we use this function pointer or variable.
Here we have declared extern in header file and using it in same source file.
what is the use of using extern here
And this function pointer is being used in other source files without extern declaration . iam confused with this? Generally, we have a declaration somewhere (somehere.h) and if we use it in some other file(here.h or here.c) we use extern keyword just to get this variable.
I did not quite understand the reason for using extern keyword after typedef.
Why do we use extern after the declaration of fucntion pointer in the same header file.
The extern keyword is needed to distinguish the declaration of a global data object such as a function pointer and the definition of this object.
In a header file, you should only have declarations. Definitions belong in source files and should not be duplicated in different source files. If you put definitions in header files, you end up with multiple definitions of the same symbols at link time. For historical reasons, common linkers accept these multiple definitions if they do not have initializers. Nevertheless, it is considered bad practice and should be avoided.
myfuncs.h
extern initMyfuncs_t _initMyfuncs; // declaration of function pointer
myfuncs.c
initMyfuncs_t _initMyfuncs = some_function; // actual definition of the pointer with optional initializer.
The confusion comes from the typedef of a function pointer, different from a function prototype. A function prototype is a declaration even without an extern keyword.
extern int a;
is the declaraton of a. It is (just) a promise to the compiler a will be around at link-time.
It's actual definition needs to be done elsewhere, typically in a .c file via
int a = 42; /* The initialiser is optional, if missing it will default to '= 0'. */
The above concept is the same for any type.
A header file can be included in many source files. Without the extern keyword, also storage would be alocated. Without the extern keyword in the header file, this storage would be allocated in every source file that includes the header file. At link time, the linker will now complain about multiple symbols (some linkers solve this gracefully).
To avoid this, yet not having to separately declare the objects in a source file, I use the following method:
/* myInclude.h */
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myGlobalVar;
/* someFile.c */
#include "myInclude.h"
/* main.c */
#define EXTERN
#include "myInclude.h"
This will allocate storage for the object in main.c and declare it as extern in all other souce files including the header file.
i think i got the answer for that
1.without extern in header there would be a redefinition error , if we use the same variable (initMyfuncs_t _initMyfuncs = nullptr;)
Or we can just mention typedef function pointer and initialize a varaible in source file
myfuncs.h
typedef void(*initMyfuncs_t)(int*, int*, int*);
and initiliaze it in source myfuncs.c
initMyfuncs_t _initMyfuncs = nullptr;
and if we need declaration in header file then
myfuncs.h
typedef void(*initMyfuncs_t)(int, int, int);
extern initMyfuncs_t _initMyfuncs;
and initialize it in source file
initMyfuncs_t _initMyfuncs = nullptr;
And finally when this header file is used in any source file, this variable can be used too as we have extern declared in it

calling a function from a .h file [duplicate]

This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 8 years ago.
file1.c => includes file1.h
file1.h => has a struct:
typedef struct {
unsigned char *start;
unsigned int startInt;
}debugPrint;
file1.c => creates a struct object:
debugPrint dp;
file1.c => an int is given into struct:
dp.startInt = 10;
file1.c => has a function:
void function1(debugPrint dp) {
printf("%d", dp.startInt);
}
file2.h => has a function call to file1.c function which is declared before the call:
void function1(void);
function1();
Questions is:
Is it ok that the file2.h calls a function from file1.c
how can i pass the dp.startInt value to file2.h so that the value 10 that was set into dp.startInt in file1.c can be used in the funtion call in file2.h ?
It is needed to be called from file2.h since this file handles dynamic variable exchange between a html page and the file2.h file => data from file2.h function call via file1.c is sent to Html page. But i wont go more into the passing variable to html page since i don't know how it is made. It is a mechanism of openPicus web server example.
But if you know a good solution for this one. i would appreciate it. I'm not so familiar with this kind of code so that is also an issue here :)
But since i think this description is not good enough, here is the files:
file1.c:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include "test1.h"
// Define printStruct
void printStruct (debugPrint dp) {
printf("%u", dp.startInt);
}
int main ()
{
dp.startInt = 10;
getch();
}
file1.h:
typedef struct {
// For the motorEncoder value
unsigned char filename[20];
char ownMsg[10];
unsigned char *start;
unsigned char *timeInSeconds;
unsigned char *distanceInCm;
unsigned char *numberOfShots;
unsigned char *shutterCompensation;
unsigned char *direction;
unsigned char *cancel;
unsigned char *dutyCycle;
unsigned int cancelInt;
unsigned int startInt;
unsigned int dutyCycleInt;
unsigned int directionInt;
}debugPrint;
// Create struct object called dp
debugPrint dp;
// declare printStruct
void printStruct (debugPrint dp);
file2.h: (this file is totally needed to pass the dynamic values) I didn't put any includes since im not sure how i should include the .h files and from where i should include them.
// Call printStruct function
printStruct(dp);
part of file2.h actual code: (AND YES file2.h A HEADER FILE). FOR ME THIS SEEMS LIKE THE FUNCTIONS ARE FIRST DECLARED AND THEN ONE OF THEM IS USED IN THE H FILE => the HTTPPrint() function from where a function called HTTPPrint_stepCounter(); is called. That function is defined then in file1.c and it just prints some dynamic data to a http page. And as said this is how openPicus has done it and i am just trying to modify it.
void HTTPPrint(DWORD callbackID);
void HTTPPrint_led(WORD);
void HTTPPrint_stepCounter(void);
void HTTPPrint(DWORD callbackID)
{
switch(callbackID)
{
case 0x00000017:
HTTPPrint_led(0);
break;
case 0x00000059:
HTTPPrint_stepCounter();
break;
default:
// Output notification for undefined values
TCPPutROMArray(sktHTTP, (ROM BYTE*)"!DEF", 4);
}
return;
}
void HTTPPrint_(void)
{
TCPPut(sktHTTP, '~');
return;
}
Some tips for someone new to the C language:
There's an important difference between definition and declaration.
Definition is what actually creates the function or variable. Each function must be defined exactly once. Either in a *.c source file, or in a library.
Declaration creates an entry in the symbol table, that says the function or variable exists... somewhere... and here's its data type. Declarations can be duplicated without any effect.
We put function definitions in *.c source files. (And also in libraries, but that's an advanced build topic...)
We put public or extern function declarations in *.h header files.
We put shared extern variable declarations in *.h header files, so that other source units can share the same variable.
We put shared typedef structure declarations in *.h header files, so that other source units can share the same data type.
We do not put variable declarations in *.h header files if they aren't extern, or if they are initialized. The initial value belongs in the *.c file.
Function definitions usually don't belong in a *.h header file, because it's possible in a large project, that the header file could be included (read by the compiler) more than once. That would cause a compiler error, because then there would be more than one definition of that function. Even if it's literally a repeat of the same source code, there can be only one.
The quote about file2.h having a function call to file1.c function is not correct, function1(); could be either a declaration or a function call depending on context:
// declaration of a function named foo
void foo(void);
//
// declaration of a function named bar
// equivalent to declaring void bar(void);
bar();
//
// definition of a function named foo
void foo(void)
{
// call (or invoke) the function named bar
bar();
}
Another small point, about arrays: it's pretty strange to declare an array of one element debugPrint dp[1], since that declaration creates an object that will be referred to as dp[0]. This makes me think you may be trying to avoid the use of pointers... it would be more straightforward to just declare debugPrint dp and then the object is referred to as dp. Arrays make sense if you have more than one related object of the same type, but for just one object, it's a pretty unusual usage.
C is a very flexible programming language that gives free access to lots of low-level tricks. Both a blessing and a curse... For someone just getting started with the language, it's important to read other people's code examples as much as you can, to help learn how things are usually done. There are lots of extremely clever ways to use the language (e.g. Duff's Device) but in most cases, you're better off sticking with the most straightforward and customary way of solving the problem.
See also: What is the difference between a definition and a declaration?
You claim that file2.h contains:
void function(void);
function1();
But these lines refer to two different functions.
This problem is now fixed; both names are function1
If the function1(); appears outside any function, it is a (very sloppy) function declaration, not a function call. If it is inside some function, what is that function definition doing inside the header file. It would need to be an inline function to have much legitimacy.
The problem below is now fixed; the types are consistent.
Additionally, you say: an integer is given into struct: dp[1].startInt = 10;. The compiler complains that you shouldn't assign integers to pointers (since startInt is declared as a pointer, not an int). You need to get your code to compile without such complaints.
... There are two versions of the structure defined, one at the top of the question where startInt is an unsigned int *startInt; and one later on where the declaration is unsigned int startInt. Please make your question self-consistent! ...
This problem has been fixed now; dp is a simple structure.
Also note that you created debugPrint dp[1]; so your initialization is trampling out of bounds; the maximum valid index for the array is 0.
If code in file2.c needs to access the internals of the structure type declared in file1.h, the header file1.h should be included in file2.c. You can declare your dp array in the header too. A header should include other headers only if the functions it defines expose types defined in the other headers. For example, if the structure defined in file1.h included a FILE *db_fp; element, then file1.h should #include <stdio.h> to ensure that the code in file1.h would compile regardless of what else the code using file1.h includes.

Declaration of structures in multiple files

If I include the declaration of the part structure(for example) into two different files,
will part variables in one file be of the same type as part variables in the other file?
Yes, they're of the same type if the declarations are structurally the same. If this weren't true, it wouldn't be possible to call library functions that use structure parameters, since the caller and callee are in different files.
The declarations don't have to be literally the same. As long as they specify the same types in the same order, things like member names and the name of the struct type don't have to match. So if you do:
file1.c:
struct {
int i;
char c;
} var1;
and in file2.c:
typedef struct newstruct {
int v1;
char v2;
} newstruct_t;
newstruct_t var2;
then var1 and var2 are of the same type.
The full details are a bit more complex, but this is a useful approximation.
However, programming like this will be confusing. If you intend to share a type between files, you should put the declaration in a header file, and #include it in all the source files that use it.

Resources