Including source

S

squaretriangle

Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?
2. What are the practical virtues of not doing it? I can think of
reasons *to* do it.
 
S

santosh

Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?

Headers usually get included into multiple translation units. Such
multiple inclusion of a .c file is likely to be an error.
2. What are the practical virtues of not doing it?

If you find yourself needing to include code sequences into multiple
files, you might consider multiple modules and linking. It greatly
reduces chances for conflict and code size. Any errors can be corrected
in one place instead of in umpteen files.
I can think of reasons *to* do it.

Okay, what are they?
 
E

Eric Sosman

Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?

The C Standard uses the word "deprecated" only twice,
neither time in connection with source inclusions.
2. What are the practical virtues of not doing it? I can think of
reasons *to* do it.

The primary motivation for creating a header is to make
it easy to incorporate the same chunk of source in different
compiled modules. If the "chunk" contains definitions, each
module that includes it adds its own copy of the definition
to the finished program. For externally-linked identifiers
that's illegal: You can't have two foo() functions in the
same program if both have external linkage. For internally-
linked identifiers it's legal but questionable: You can have
as many `static int foo()' functions as you like, but do you
really want all those redundant copies lying around?

That said, there are a few circumstances where definitions
make sense in headers. One is when the header is generated
by some kind of "helper" program in the build process and is
intended for inclusion in only one compilation anyhow. Another
is when the definitions are of `static inline' functions that
you've decided are really worth having multiple copies of. Still
another is when the definitions are completed by macros defined
prior to the inclusion, generating different code for different
inclusions depending on the other macros. There are probably
a few more use cases that don't occur to me right now -- but
taken all in all, the situations that call for definitions in
headers are fairly uncommon.
 
S

squaretriangle

Okay, what are they?

I was speaking from presumption; I'd never actually gone and tried
it. I was thinking that including a conditional to check if the file
had already been included would work, but on reflection it obviously
wouldn't. I was thinking that it would be more modular and easy to
deal with if a "library" could be included as one file, without having
to also think about linking to anything.
 
S

santosh

I was speaking from presumption; I'd never actually gone and tried
it. I was thinking that including a conditional to check if the file
had already been included would work, but on reflection it obviously
wouldn't.

It would work. That's exactly the mechanism that headers use. However
then you've defeated your own purpose.
I was thinking that it would be more modular and easy to
deal with if a "library" could be included as one file, without having
to also think about linking to anything.

A library by definition is called from several files and several
programs. You usually _don't_ want to include a fresh copy of a
function in each module that uses it. That's why multiple modules and
linking were developed.

The whole issue proceeds from the observation that, in C at least, you
generally need a separate declaration in each place it's needed, but
usually one definition of an object or function suffices. In fact for
external objects or functions, you cant have more than one active
definition.

A prominent exception to this observation are macros.
 
R

Richard Heathfield

(e-mail address removed) said:
Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?

Most good programmers don't #include C source because in almost all
circumstances it's a bad idea.
2. What are the practical virtues of not doing it?

This is a little like listing the practical virtues of not nailing your
foot to the floor. Mostly, you're very likely to be heading for trouble
the moment you try to #include that C source in two separate parts of your
program. Also, of course, it does mean that you have to compile everything
all the time, instead of just compiling the bits that have changed - which
is a complete waste of time.
I can think of reasons *to* do it.

I can't.
 
T

Tor Rustad

Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?

The way we use a function multiple places, is by placing the prototype
of the function in a header file, e.g. like this:

extern void function(void);

If you rather include the source of the function multiple places, this
leads to bloat, slower compile and possibly hard to maintain code.

2. What are the practical virtues of not doing it? I can think of
reasons *to* do it.

In 20 years of C programming, I have never needed or wanted to do it. :)

The only reason I can think of right now, is if I somehow wanted to
avoid using a function pointer as a parameter to an interface, for
tuning purposes. It sound like a bad idea...
 
P

Pierre Asselin

santosh said:
(e-mail address removed) wrote:
1. Including a .c file with #include,
[ ... ]
I can think of reasons *to* do it.
Okay, what are they?

I'm not the OP but I found it useful to #include source files when
compiling unit tests. It's a bit idiosyncratic and is not done
when compiling the production code.

So it works, there is no prohibition against it, but it's not
normal.
 
B

Ben Pfaff

1. Including a .c file with #include, [...]
2. What are the practical virtues of not doing it? I can think of
reasons *to* do it.

One good reason is a social one: programmers do not expect .c
files to be #included, so if you #include .c files, you will
surprise other programmers reading your code, making it more
difficult for them to maintain and enhance it.
 
T

Thad Smith

Richard said:
(e-mail address removed) said:


Most good programmers don't #include C source because in almost all
circumstances it's a bad idea.

I agree. There are special cases, though, where it makes sense. One is
using macros to implement function templates in C:

-------
file: sort_ulong.c
#define TYPE unsigned long
#define TYPENAME ulong

#include "sorttype.ct"
-------
file: sorttype.ct
/* sort function template
** The following macros must be defined:
** TYPE - C type of array element to be sorted
** TYPENAME - characters appended to function name
*/
#include <stdlib.h>

#define JOIN(a,b) JOIN2(a,b)
#define JOIN2(a,b) a ## b

/* void sort_TYPENAME (TYPE *a, size_t n) */
void JOIN(sort_,TYPENAME) (TYPE *a, size_t n) {
TYPE t; /* temp item */
/* generic sort code goes here */
}
-------
 
B

Ben Pfaff

Thad Smith said:
Richard said:
Most good programmers don't #include C source because in almost all
circumstances it's a bad idea.
I agree. [...]

Not much of an answer, though. "I don't do <foo> because in
almost all circumstances it's a bad idea."
 
R

Richard Heathfield

Ben Pfaff said:
Thad Smith said:
Richard said:
Most good programmers don't #include C source because in almost all
circumstances it's a bad idea.
I agree. [...]

Not much of an answer, though. "I don't do <foo> because in
almost all circumstances it's a bad idea."

That's why I went on to say:

"Mostly, you're very likely to be heading for trouble the moment you try to
#include that C source in two separate parts of your program. Also, of
course, it does mean that you have to compile everything all the time,
instead of just compiling the bits that have changed - which is a complete
waste of time."

It is true that some good programmers do #include C source on vanishingly
rare occasions, but it was my considered opinion that the chances are very
slim indeed of an explanation of that fact being useful to someone who (at
a guess) is at a comparatively early stage in his or her C education.

About a decade ago, I wrote something similar to Thad's hack, and it was
(rightly, IMHO) rejected at code review. The sigh was along the lines of
"yes, all right, Richard, very good - now go write something we can read".

About five years ago, I saw something of the kind in the graphics rendering
code for a browser, with perhaps slightly more justification - it was
clear to me that the programmer /wanted/ to write an inline function, but
the code had to work on so many different platforms that using the
"inline" keyword was simply not an option. Evidently, he considered the
performance benefits to outweigh the maintenance cost, and he may well
have been right. I suspect he was, actually, but it wasn't my job to
establish this either way, so I didn't.
 
J

James Kuyper Jr.

Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?
2. What are the practical virtues of not doing it? I can think of
reasons *to* do it.

I've #included *.c files, but only for one specialized use: creating
wrappers for existing functions that modify the normal behavior of those
functions, and need to be link compatible with code that calls those
functions by name. I usually use this when creating unit test drivers.

wrapper.c:

#define origfunction myfunction
// file.c defines origfunction(). With the above #define, it actually
// ends up defining myfunction()
#include "file.c"
#unddef origfunction

long origfunction(int a, double b, char *c)
{
if(special_handling)
{
// implement special handling
}
else
{
return myfunction(a, b, c);
}
}


I prefer this over creating a modified copy of file.c, because I don't
need to make changes to wrapper.c, just because file.c changes, unless
the interface to origfunction() changes. This is particularly helpful
when origfunction() is part of a 3rd party library delivered as source
code, which describes all of the 3rd party libraries we link to in my group.
 
B

borkhuis

A library by definition is called from several files and several
programs. You usually _don't_ want to include a fresh copy of a
function in each module that uses it. That's why multiple modules and
linking were developed.

I do use it (but very rarely) for libraries. I have a library that
interfaces to a device driver, and can be used on several platforms
with different drivers for the same device. Most of the code is
generic, but part of it is platform dependent. I only want the defined
interface to be visible outside of the library, and not my internal
functions, so I want to define these functions as static.
I have four options to do this AFAIK:
I can create a number of copies of the generic code for each of the
platforms, which adds to the maintenance.
Or I can add the code for all the platform to the original file, and
use #ifdef to select the code I need for a platform.
Or I can create a source-file per platform that is included for a
specific platform only, also using #ifdef
Or do not define the functions as static.

We are using the third option, as this option is easier to maintain
than the first 2. The last one contradicts the "for internal use only"
rule for these functions, so this is a no-op.

Kind regards,
Johan Borkhuis
 
M

Mike Wahler

Regarding either of the following:

1. Including a .c file with #include,
2. Including source code contained in a .h header file with #include

I have 2 questions.

1. Is the reality of most programmers not doing this because of
popular habit, or is it officially deprecated in one of the C
standard(s)?
2. What are the practical virtues of not doing it? I can think of
reasons *to* do it.

1. The C language does not specify that a particular file
'extension' be used with a source file or header, with
the single exception that the standard library headers
have names which end in ".h". And note that there's no
requirement that a standard header be a file at all (but
they typically are).

2. All these files are 'plain text' files, and you can name
them anything you want. (However some implementations do
impose some naming requirements, and/or make assumptions
based upon the names used).

3. The #include directive does something quite simple: it
inserts the text of the file referred to by it into the
file containing the directive, at the point the directive
appears.

4. How you use the #include mechanism will depend upon the
contents of the various files. For example, a 'header'
file is typically included in several source files,
so should have only declarations, not definitions, or
multiple definitions of the same entities would occur at
link time.

5. There's no reason (other than convention or local coding
standards), you cannot #include a ".c" file (or other text
file) into any other file. The key is to think about what
these files contain, and whether a particular #include
directive makes sense.


-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top