Making function private/ not supplying declaration in header file

Discussion in 'C Programming' started by Daniel Nichols, Jun 14, 2004.

  1. I've noticed that in a C module (.c, .h file combination) that if you
    create a function's definition before it is used in other functions
    than a declaration is not necessary. I believe if the compiler can
    find the definition of the function prior to encountering the use of
    the function it will generate the prototype itself.

    I don't currently use this feature, I explicitly create declarations
    for all functions in a header file. However, I do think this feature
    would be jolly useful for functions which can be thought of as private
    to the module and nobody else ever needs to use. As well as not
    actually appearing in the header file, so nobody will try to use it,
    if the signature for this function is changed no changes are necessary
    to the header file and we therefore remove a whole set of dependencies
    when we re-compile.

    Is the consensus that this is a good compiler side-effect to use or is
    it best avoided, to become de-supported, already not supported by C++,
    etc.

    Thanks,
    Daniel.
    Daniel Nichols, Jun 14, 2004
    #1
    1. Advertising

  2. Thanks everybody for feedback.

    I'm familiar with the "Pascal style" of function layout in files as I
    do a lot of Oracle PL/SQL programming which is based a little on ADA
    and Pascal. This is why I first tried the idea of missing the
    prototype out of the header. I would never put a function in a PL/SQL
    specification file if it was private but do so all the time in C.

    I can easily create static prototypes in my .c files for these
    private/internal functions. It will certainly help minimise
    re-compiles when these "internal" functions change their prototypes.

    However, I'm still wondering if it is easier to maintain the C file if
    you don't duplicate the prototype: once before use (at the top of the
    ..c file) and then again since the function is defined before it's
    first use (as "Default User" points out.)

    It's just Eric Sosman states it is good practice to declare a function
    before use. Is it because, if you do prototype explicitly you can
    position the function physically anywhere in the file?

    Obviously, things work as they are but I don't want to have to go and
    duplicate prototypes up at some later time after a code review from
    someone who thinks prototypes are essential and required for C99.
    Daniel Nichols, Jun 14, 2004
    #2
    1. Advertising

  3. Daniel Nichols

    Eric Sosman Guest

    Re: Making function private/ not supplying declaration in headerfile

    Daniel Nichols wrote:
    > Thanks everybody for feedback.
    > [...]
    > It's just Eric Sosman states it is good practice to declare a function
    > before use. Is it because, if you do prototype explicitly you can
    > position the function physically anywhere in the file?


    Under C99 rules, every function must be declared before
    the first reference to it. Under C89, a preceding declaration
    can be omitted if the function returns `int' and has an argument
    list compatible with the K&R form; all other functions must be
    declared before use, even in C89.

    There are a couple of reasons why it's "good practice" to
    declare before use even when C89 would let you get away without
    it. First, there's the likelihood that you will someday want
    to move the code to a C99 environment, where the declaration
    becomes mandatory. Second, no "variadic" function has a K&R-
    compatible argument list (the `...' can't be expressed in K&R),
    so it follows that every variadic function must be pre-declared.
    Third, it's surprisingly difficult to determine whether a given
    function has a K&R-compatible argument list! For example,

    int a(size_t x) { ... }
    int b(time_t x) { ... }
    int c(char x) { ... }
    int d(enum foo x) { ... }

    may be K&R-compatible on some implementations but not on others.

    "Good practice" quite often amounts to little more than
    avoiding unpleasant surprises.

    The advantage of writing pure declarations (the above, but
    replacing each `{ ... }' with `;') is that if you stick 'em all
    somewhere near the top of the file you can then arrange the
    actual function definitions in whatever order makes it easiest
    for you to read. The disadvantage, as you noted in some text I
    snipped, is that when you write both a declaration and a definition
    you are repeating yourself and thus have the opportunity to
    contradict yourself -- the compiler will complain about the
    contradiction, but it's an error that simply can't arise if you use
    the "Pascal style."

    And, of course, there are some situations where declarations
    are unavoidable. Mutually recursive functions, for example:

    double a(void) {
    ...
    x = b();
    }

    double b(void) {
    ...
    y = a();
    }

    .... cannot be made to work without introducing a declaration
    of b() separate from its definition.

    > Obviously, things work as they are but I don't want to have to go and
    > duplicate prototypes up at some later time after a code review from
    > someone who thinks prototypes are essential and required for C99.


    You're still confusing "declaration" and "prototype."
    Function declarations (remember, a definition is also a
    declaration) are sometimes required and sometimes optional
    in C89, are always required in C99, and are always good
    practice under either Standard. Argument-list prototypes
    are mandatory for variadic (`...') functions and for functions
    that accept "narrow" argument types (`float' and usually some
    others), optional for fixed-list functions with "wide"
    arguments, and good practice always, under both Standards.

    Here are two function definitions (and declarations),
    one with a prototype and one without:

    double f(int a, float b, char *c)
    { ... }

    double g(a, b, c)
    int a;
    float b;
    char *c;
    { ... }

    Here are correct declarations of these functions, using
    prototypes:

    double f(int, float, char*);
    double g(int, double, char*);

    Note the declared type of the second argument to g(). It's
    hard in general to get this right, and that's one reason
    not to mix'n'match ANSI prototypes with K&R functions.

    Here is a correct declaration of g(), with no prototype:

    double g();

    It is not possible to declare f() correctly without using
    a prototype -- which is a reason not to mix'n'match ANSI
    function definitions with K&R prototypeless declarations.

    --
    Eric Sosman, Jun 14, 2004
    #3
  4. Re: Making function private/ not supplying declaration in header file

    Thanks for your detailed explanation. It's now clear what to do.
    Daniel Nichols, Jun 14, 2004
    #4
  5. Daniel Nichols

    CBFalconer Guest

    Daniel Nichols wrote:
    >
    > I'm familiar with the "Pascal style" of function layout in files
    > as I do a lot of Oracle PL/SQL programming which is based a
    > little on ADA and Pascal. This is why I first tried the idea of
    > missing the prototype out of the header. I would never put a
    > function in a PL/SQL specification file if it was private but do
    > so all the time in C.


    The so-called Pascal style is just fine. A complete function
    definition constitutes a valid prototype, and as long as it
    precedes use no separate prototype is ever required. In fact it
    should be avoided, because it just one more place to make a
    copying mistake.

    There are two fundamental reasons for prototypes. 1. To allow
    mutual recursion. 2. To allow construction of header files,
    which in turn are used to publish the interface to a compilation
    unit.

    A third, not necessary, reason is to remove the need for ordering
    in the source file. I consider this a hindrance, since without it
    I know the source for a routine (or a prototype) will be found by
    looking towards the beginning. (You can get the same effect in
    Pascal source by declaring all functions/procedures as "forward" -
    very ugly)

    --
    A: Because it fouls the order in which people normally read text.
    Q: Why is top-posting such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    CBFalconer, Jun 14, 2004
    #5
  6. Daniel Nichols

    Jack Klein Guest

    On Mon, 14 Jun 2004 20:36:15 GMT, CBFalconer <>
    wrote in comp.lang.c:

    > Daniel Nichols wrote:
    > >
    > > I'm familiar with the "Pascal style" of function layout in files
    > > as I do a lot of Oracle PL/SQL programming which is based a
    > > little on ADA and Pascal. This is why I first tried the idea of
    > > missing the prototype out of the header. I would never put a
    > > function in a PL/SQL specification file if it was private but do
    > > so all the time in C.

    >
    > The so-called Pascal style is just fine. A complete function
    > definition constitutes a valid prototype, and as long as it


    No, a complete function definition necessarily constitutes a
    declaration. It may or may not also provide a prototype.

    int func(x, y)
    int x, y;
    {
    return x + y;
    }

    ....provides a declaration of func() as a function accepting an
    unspecified, but fixed, set of arguments, but it is not a prototype.
    This is all the declaration that is needed for non-variadic functions
    even in C99.

    > precedes use no separate prototype is ever required. In fact it
    > should be avoided, because it just one more place to make a
    > copying mistake.
    >
    > There are two fundamental reasons for prototypes. 1. To allow
    > mutual recursion. 2. To allow construction of header files,
    > which in turn are used to publish the interface to a compilation
    > unit.
    >
    > A third, not necessary, reason is to remove the need for ordering
    > in the source file. I consider this a hindrance, since without it
    > I know the source for a routine (or a prototype) will be found by
    > looking towards the beginning. (You can get the same effect in
    > Pascal source by declaring all functions/procedures as "forward" -
    > very ugly)


    Some coding standards, including MISRA C, require that a prototype be
    in scope not only at the call, but also at the definition of all
    functions, and that includes static ones.

    PCLint will diagnose a failure to meet this requirement if its MISRA C
    rule set is used, even for static functions.

    There is at least one C compiler (CodeWarrior) that has an option to
    emit a warning message if this is violated, even for static functions.

    The tools above will also emit a warning for any function with
    external linkage (except for main()) defined without a prototype in
    scope.

    I personally insist on this requirement in the coding requirements for
    all projects that I participate in. Otherwise larger projects with
    multiple programmers would quickly descend into chaos.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Jun 15, 2004
    #6
  7. Daniel Nichols

    CBFalconer Guest

    Jack Klein wrote:
    > CBFalconer <> wrote in comp.lang.c:
    >

    .... snip ...
    >>
    >> The so-called Pascal style is just fine. A complete function
    >> definition constitutes a valid prototype, and as long as it

    >
    > No, a complete function definition necessarily constitutes a
    > declaration. It may or may not also provide a prototype.
    >
    > int func(x, y)
    > int x, y;
    > {
    > return x + y;
    > }
    >
    > ...provides a declaration of func() as a function accepting an
    > unspecified, but fixed, set of arguments, but it is not a
    > prototype. This is all the declaration that is needed for
    > non-variadic functions even in C99.


    I always forget that, because I never use old fashioned function
    definitions. They were the prime insecurity reason I refused to
    use C in the old days.

    --
    A: Because it fouls the order in which people normally read text.
    Q: Why is top-posting such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    CBFalconer, Jun 15, 2004
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?U3llZCBHaGF5YXM=?=

    Problem writing cookie when supplying Path property

    =?Utf-8?B?U3llZCBHaGF5YXM=?=, May 6, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    431
    =?Utf-8?B?bWljcm9zb2Z0LnB1YmxpYy5kb3RuZXQuZnJhbWV3
    May 6, 2005
  2. sp
    Replies:
    3
    Views:
    689
    Philippe Poulard
    Jan 27, 2006
  3. Daniel Nichols
    Replies:
    5
    Views:
    434
  4. Torsten Mohr
    Replies:
    1
    Views:
    288
    Fredrik Lundh
    Jan 17, 2005
  5. Jim McGivney
    Replies:
    1
    Views:
    442
    =?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=
    Sep 3, 2006
Loading...

Share This Page