An external struct declaration, but the struct definition is just above - c

I double-checked all the similar questions here, I really hope not to duplicate.
I am intrigued by the the following extract from stdio.h:
typedef struct _iobuf {
/* Members here omitted ... */
} FILE;
extern FILE _iob[20];
We define a new type named FILE by using the struct syntax. Just after that, we declare an extern variable _iob of type FILE. Therefore, this variable must come from another place.
But, since the definition of FILE is in this file, how can it be possible? I see two possibilities only.
The first is to have something like:
#include <stdio.h>
FILE _iob[20] = /* definition */
The second is to have another source file where the struct is copy-pasted and the variable declared, I guess a very bad practice that we can omit.
Since I am a self-learner, I would be very happy to receive a confirm of my understanding.Thanks!

Either:
somewhere in the library source code files, there is text as you describe, an inclusion of <stdio.h> followed by a definition of FILE _iob[20], or
somewhere in the library source code files, there is a definition of _iob written in a programming language other than standard C.
The latter may be assembly language, non-standard C with extensions, or something else. An implementation of C is not required to use only C source code to define itself.
In general, it is good practice for the source file that defines an object to also include its own header. A primary purpose of a header file is to tell other source files about things defined in the associated source file. But including the header file in the source file serves another purpose: The compiler will see both the declarations in the header and the definitions in the source file and will issue error messages if they are incompatible. So this provides a check that catches typos or other errors when building the library.

Related

How to use struct as argument of a function when the struct is declared in another file?

I'm writing a c project and I'm trying to keep all the struct declarations in the relevant .h files. This allows me to use them in any of the .c files by including the relevant header.
I'm also avoiding the inclusion of header files of my project in other header files. I guess this will make the code easier to read and maintain.
My question is how to avoid the inclusion of a header which contains the declaration of a struct in the header file that uses that struct. Is there any way of doing that?. (I didn't find an answer for this, sorry if it's duplicated).
Here is a snippet:
cmd.c
#include "cmd.h"
#include "params.h" //This allows usage of struct testPars
void move_parameters(struct testPars *testP) {
...
}
cmd.h
#ifndef CMD_H
#define CMD_H
#include "params.h" //I want to avoid this include in this file
void move_parameters(struct testPars *testP) ;
#endif
params.h
#ifndef PARAMS_H
#define PARAMS_H
struct testPars {
char name[16];
double value;
};
#endif
Overall, there's a lot of confusion about proper program design here.
I'm trying to keep all the struct declarations in the relevant .h files. This allows me to use them in any of the .c files by including the relevant header.
This is acceptable practice for quick & dirty programming where you have no private encapsulation, or if the structs are of a simple nature.
But for professional programs where the structs represent more complex ADTs etc, you should only keep a forward declaration in the header files, and define the struct inside the corresponding c file. This leads to private encapsulation and modularisation, i.e. good program design. (Search for examples of "opaque type" or "opaque pointers". The formal term for such forward declarations is incomplete type.)
What you are trying to do sounds like the above but completely backwards: expose the definition to the caller, but don't use it yourself. And obviously you can't use a struct that you haven't included and made visible to your program, because that doesn't make any sense.
I'm also avoiding the inclusion of header files of my project in other header files. I guess this will make the code easier to read and maintain.
This is a bad idea. Each of your header files is to be regarded as the public documentation of what the corresponding c file does and how it should be used. While the c file can be regarded as private data, the content is nothing that the caller should concern themselves with.
An important part of that header file documentation is to list all dependencies that this module has, so that other programmers can quickly take a glance at the top of your header file and immediately tell which files that are needed in order to compile this particular module.
Good program design strives for as few dependencies as possible: "loose coupling". Therefore all #includes are regarded as important information that should be put on top of the header file. Header files that aren't used should not be included.
The c file should not contain any includes except its own header file.

Accessing a typedef globally

I found some source code that I want to incorporate into a C program I am writing. Let's call it existing.c. This file contains a typedef for a struct that is required for a parameter to a function defined lower down in the file. I want to call this function in my file main.c. I know I could probably get access to the function by declaring a function prototype in main.c, but I will also need access to that struct definition to declare and call the function.
There is no .h file for existing.c, although I could of course make one, say existing.h. But if I put the typedef in existing.h, then it seems like I would have to put #include "existing.h" into existing.c, which does not seem correct from my understanding of header files. I thought their purpose was to make the code in a certain file available to other compilation units, and shouldn't be required by that file itself.
So I guess my main question is straightforward, how do I use the function defined in existing.c in my own file main.c? Can I do it without a header file, like by putting some kind of struct prototype in main.c, similar to a function prototype, or specify the struct as external or something along those lines?
Edit: I probably should have mentioned in my original post that one reason I was hoping to avoid using a header was so I could incorporate the existing.c file unaltered in case there are revisions of this source in the future. Judging from the answers this is not possible.
if I put the typedef in existing.h, then it seems like I would have to put #include "existing.h" into existing.c, which does not seem correct from my knowledge of header files.
That is precisely the thing to do: move the typedef into the existing.h header, then include that header in both the existing.c and in your code.
I thought their purpose was to make the code in a certain file available to other compilation units, and shouldn't be required by that file itself.
That is how the headers do their job - you include them both from the implementation file and from the code that uses that implementation.
Although it is possible to write a header that matches what was in the implementation, and use it without inclusion in the implementation file itself, this is not desirable: one reason why you include the header in the implementation is to let the compiler check the code against the function prototypes from the header, and produce errors for any discrepancies it may find.
then it seems like I would have to put #include "existing.h" into existing.c, which does not seem correct
That's the proper and correct way to do it.
You place declarations in a header file if more than one compilation unit needs those declarations, and the source code file containing the implementation is almost always one of the files you include the header file in.

C using a forward declaration within a function definition

I'm working on a project in which I'm forced to use some previously written code that uses many header files calling other header files. I'm trying to keep my application separated, but I still need to use many of the types and functions defined in the previous code.
I've added forward declarations in my own header files, when referencing data types declared in other header files. My problem now, is I'm trying to reference a union type from within a function definition in a source file and I'm not quite sure how to do it.
Old header file:
/* filename: include.h */
typedef union SOME_UNION_TYPE
{
int a;
.
.
}SOME_UNION_TYPE;
My source file:
/* filename: file.c */
void func()
{
SOME_UNION_TYPE A;
.
.
return;
}
I know it would be easier to just include "include.h" in my source code, but I'm trying to avoid it as much as possible. My attempt so far has been to forward declare the union in my header file, in hopes of exposing the typedef name to the compiler.
My header file:
/* filename: file.h */
union SOME_UNION_TYPE;
However, when I compile, I receive an error complaining about unknown size for A in func().
Thanks in advance for any help.
If you need to create an actual instance of the type, you need the complete declaration, not just the name.
The right thing to do in this case is to bite the bullet and include the header file that defines the type.
The #include directive is not something to be avoided. If you're concerned about other people's code polluting your code, you can make a header that includes the headers you need, and include that one directly.
Duplicating code is bad.
The other code probably includes a bunch of other headers because it needs them! You should just include the other header otherwise you are duplicating code which is bad.

Including header file causes conflicting types

So I have this struct in a header file, called it h1.h
typedef struct{
int a;
int b;
special_t test;
} randomDataType
So I include the header file that contains the declaration of special_t. None of the functions in either header file are named the same, and I don't see how circular dependencies could come into play since the functions declared in the second header file are only ever accessed through the functions declared in h1.h
Yet I have a 'previous declaration of __' error for everything in the other header. Why is this?
It sounds like you do not have multiple inclusion guards on your header files. Except in very rare cases which you will know when you get to them, C header files should be written like this:
/* This is h1.h.
This is its license.
This is what you will find here. */
#ifndef H1_H__
#define H1_H__
all declarations go here
#endif /* h1.h */
There should not be anything outside the #ifndef ... #endif block except for comments, and you need to pick the macro name so that it won't conflict with any other header -- assume that all C header files have this construct in them, or something very like it.
What this does is allow you to #include "h1.h" as many times as you like; the compiler will only process its contents once. Many compilers recognize this construct and won't even open the file again (as long as the macro is still defined). Thus, you can safely include headers from other headers (that might need only a few of the declarations) without worrying about what any other file has done.

What's the difference between using extern and #including header files?

I am beginning to question the usefulness of "extern" keyword which is used to access variables/functions in other modules(in other files). Aren't we doing the same thing when we are using #include preprocessor to import a header file with variables/functions prototypes or function/variables definitions?
extern is needed because it declares that the symbol exists and is of a certain type, and does not allocate storage for it.
If you do:
int foo;
In a header file that is shared between several source files, you will get a linker error because each source would have its own copy of foo created and the linker will be unable to resolve the symbol.
Instead, if you have:
extern int foo;
In the header, it would declare a symbol that is defined elsewhere in each source file.
One (and only one) source file would contain
int foo;
which creates a single instance of foo for the linker to resolve.
No. The #include is a preprocessor command that says "put all of the text from this other file right here". So, all of the functions and variables in the included file are defined in the current file.
The #include preprocessor directive simply copy/pastes the text of the included file into the current position in the current file.
extern marks that a variable or function exists externally to this source file. This is done by the originator ("I am making this data available externally"), and by the recipient ("I am marking that there is external data I need"). A recipient with an unsatisfied extern will cause an Undefined Symbol error.
Which to use? I prefer using #include with the include guard pattern:
#ifndef HEADER_NAME_H
#define HEADER_NAME_H
<write your header code here>
#endif
This pattern allows you to cleanly separate anything you want an outsider to have access to into the header, without worrying about a double-include error. Any time I have to open a .c file to find what externs are available, the lack of a clear interface makes my soul gem crack.
There are indeed two ways of using functions/variables across translation units (a translation unit is usually a *.c/*.cc file).
One is the forward declaration:
Declare functions/variables using extern in the calling file. extern is actually optional for functions (functions are automatically extern), but not for variables.
Implement the function/variables in the implementing file.
The other is using header files:
Declare functions/variables using extern in a header file (*.h/*.hh). Still, extern is optional for functions, but not for variables. So you don't normally see extern before functions in header files.
In the calling *.c/*.cc file, #include the header, and call the function/variable as needed.
In the implementing *.c/*.cc file, #include the header, and implement the function/variable.
Google C++ style guide has some good discussions on the pros and cons of the two approaches.
Personally, I would prefer the header file approach, as it is the single place (the header file) a function signature is defined, calling and implementation all adhere to this one piece of definition. Thus, there would be no unnecessary discrepancies that might occur in the forward declaration approach.

Resources