Making function private/ not supplying declaration in header file

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Daniel Nichols

    #1

    Making function private/ not supplying declaration in header file

    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

    #2
    Re: Making function private/ not supplying declaration in header file

    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.

    Comment

    • Eric Sosman

      #3
      Re: Making function private/ not supplying declaration in headerfile

      Daniel Nichols wrote:[color=blue]
      > 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?[/color]

      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.
      [color=blue]
      > 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.[/color]

      You're still confusing "declaratio n" 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@sun .com

      Comment

      • Daniel Nichols

        #4
        Re: Making function private/ not supplying declaration in header file

        Thanks for your detailed explanation. It's now clear what to do.

        Comment

        • CBFalconer

          #5
          Re: Making function private/ not supplying declaration in header file

          Daniel Nichols wrote:[color=blue]
          >
          > 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.[/color]

          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?


          Comment

          • Jack Klein

            #6
            Re: Making function private/ not supplying declaration in header file

            On Mon, 14 Jun 2004 20:36:15 GMT, CBFalconer <cbfalconer@yah oo.com>
            wrote in comp.lang.c:
            [color=blue]
            > Daniel Nichols wrote:[color=green]
            > >
            > > 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.[/color]
            >
            > The so-called Pascal style is just fine. A complete function
            > definition constitutes a valid prototype, and as long as it[/color]

            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.
            [color=blue]
            > 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)[/color]

            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.l earn.c-c++

            Comment

            • CBFalconer

              #7
              Re: Making function private/ not supplying declaration in header file

              Jack Klein wrote:[color=blue]
              > CBFalconer <cbfalconer@yah oo.com> wrote in comp.lang.c:
              >[/color]
              .... snip ...[color=blue][color=green]
              >>
              >> The so-called Pascal style is just fine. A complete function
              >> definition constitutes a valid prototype, and as long as it[/color]
              >
              > 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.[/color]

              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?


              Comment

              Working...