Function Wrapper: Opinions and Critique Desired

Discussion in 'C Programming' started by I.M. !Knuth, Jul 19, 2006.

  1. I.M. !Knuth

    I.M. !Knuth Guest

    A while back, I was mucking around with a recursive function. For
    brevity's sake, I'll define it like this:

    int func_recurs(int arg1, int arg2, int prev_pos)
    {
    int crnt_pos = 0;
    int result;

    /* stuff happens to arg1, arg2, and crnt_pos */

    func_recurs(arg1, arg2, (prev_pos + crnt_pos) );

    return result;
    }

    The critical part here (as I'm sure you've figured out already) is that
    prev_pos (the previous position) of the last recursion is combined with
    crnt_pos (the current positon) of the present recursion and passed along
    to become the prev_pos of the next recursion.

    But written this way, I had to remember that any call to func_recurs()
    always had to look like this:

    func_recurs(arg1, arg2, 0);

    Frankly, I thought that constant 0 dangling at the end was rather
    inelegant. Then it struck me that maybe I could "hide" func_recurs
    inside another function so that I wouldn't have to strain my brain
    remembering about that pesky third argument; something like:

    func_lazymemory(int arg1, int arg2)
    {
    func_recurs(arg1, arg2, 0);
    }

    Being new to C, I felt pretty clever for coming up with this all on my
    own. But then I thought: "Bah! Smells of kludge. There must be a
    better way."

    So I changed it to:

    int func_recurs(int arg1, int arg2)
    {
    --> static int prev_pos; /* conveniently init'd to 0 on 1st call */
    int crnt_pos = 0;
    int result;

    /* stuff happens to arg1, arg2, and crnt_pos */

    --> prev_pos += crnt_pos; /* adjust for next recursion */
    --> func_recurs(arg1, arg2);
    --> prev_pos -= crnt_pos; /* restore for current recursion */

    return result;
    }

    Drawing your attention to the four "-->" lines, I then thought: "Boy is
    that ugly", but I no longer felt I'd somehow cheated inside my code. I
    packed away the function and forgot about it ... until tonight.

    Tonight I was browsing through some months' old threads on clc and came
    across one that discussed function wrappers. "Cool," I thought. A
    response referenced the FAQ, so I pulled it up and had a read. So, my
    clever idea is old hat. Figures! :-D

    I started thinking again about how I dealt with that function and came
    up with some questions and concerns:

    1a) Is my use of a wrapper appropriate (or am I ignorant of some wrapper
    rule or style convention)?

    1b) Wouldn't the wrapper be improved (and the program conserve some
    storage) if it were re-written to pass pointer values like this?

    func_lazymemory(int *arg1, int *arg2)
    {
    func_recurs(arg1, arg2, 0);
    }

    2a) Is one of my solutions better/cleaner/preferable over the other?

    2b) Or are they equivalent, and picking one is a matter of (my) personal
    style?

    3) Is there some other (maybe obvious) solution to ditching that third
    argument that I've somehow overlooked?


    Thanks for your attention.


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 19, 2006
    #1
    1. Advertising

  2. I.M. !Knuth

    Morris Dovey Guest

    I.M. !Knuth (in Xns98055B40DA1711011011@81.174.50.80) said:

    | 3) Is there some other (maybe obvious) solution to ditching that
    | third argument that I've somehow overlooked?

    There is usually some other method (no matter what you're doing) :)

    I have two short pieces of recursive code that you might find
    interesting:

    http://www.iedu.com/mrd/c/getsm.c and
    http://www.iedu.com/mrd/c/getsmx.c that deal with a similar situation.

    The two are functionally equivalent; but the second module "cheats" in
    that it uses a gcc extension to allow embedding one function
    declaration inside another. It's non-standard but may have some value
    as a thought-provoking device.

    --
    Morris Dovey
    DeSoto Solar
    DeSoto, Iowa USA
    http://www.iedu.com/DeSoto
     
    Morris Dovey, Jul 19, 2006
    #2
    1. Advertising

  3. On Wed, 19 Jul 2006 06:33:14 +0000 (UTC), "I.M. !Knuth"
    <> wrote:

    >A while back, I was mucking around with a recursive function. For
    >brevity's sake, I'll define it like this:
    >
    > int func_recurs(int arg1, int arg2, int prev_pos)
    > {
    > int crnt_pos = 0;
    > int result;
    >
    > /* stuff happens to arg1, arg2, and crnt_pos */
    >
    > func_recurs(arg1, arg2, (prev_pos + crnt_pos) );
    >
    > return result;
    > }
    >
    >The critical part here (as I'm sure you've figured out already) is that
    >prev_pos (the previous position) of the last recursion is combined with
    >crnt_pos (the current positon) of the present recursion and passed along
    >to become the prev_pos of the next recursion.
    >
    >But written this way, I had to remember that any call to func_recurs()
    >always had to look like this:
    >
    > func_recurs(arg1, arg2, 0);
    >
    >Frankly, I thought that constant 0 dangling at the end was rather
    >inelegant. Then it struck me that maybe I could "hide" func_recurs
    >inside another function so that I wouldn't have to strain my brain
    >remembering about that pesky third argument; something like:
    >
    > func_lazymemory(int arg1, int arg2)
    > {
    > func_recurs(arg1, arg2, 0);
    > }
    >
    >Being new to C, I felt pretty clever for coming up with this all on my
    >own. But then I thought: "Bah! Smells of kludge. There must be a
    >better way."
    >
    >So I changed it to:
    >
    > int func_recurs(int arg1, int arg2)
    > {
    >--> static int prev_pos; /* conveniently init'd to 0 on 1st call */


    Just a nit. Static variables are initialized prior to your program
    beginning execution and independent of your function.


    Remove del for email
     
    Barry Schwarz, Jul 20, 2006
    #3
  4. Barry Schwarz <> writes:
    > On Wed, 19 Jul 2006 06:33:14 +0000 (UTC), "I.M. !Knuth"
    > <> wrote:

    [...]
    >>So I changed it to:
    >>
    >> int func_recurs(int arg1, int arg2)
    >> {
    >>--> static int prev_pos; /* conveniently init'd to 0 on 1st call */

    >
    > Just a nit. Static variables are initialized prior to your program
    > beginning execution and independent of your function.


    True -- but, by the as-if rule, an implementation conceivably *could*
    delay the initialization until the first call. (Nothing outside the
    function can see the variable before that and detect that it hasn't
    been initialized. Local static variables can be seen via pointers
    outside the function that defines them, but there's no way to
    initialize such a pointer before calling the function.)

    But I can't think of a good reason for an implementation to do such a
    silly thing.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 20, 2006
    #4
  5. I.M. !Knuth

    I.M. !Knuth Guest

    Morris Dovey <> wrote:

    <snip>
    > I have two short pieces of recursive code that you might find
    > interesting:
    >
    > http://www.iedu.com/mrd/c/getsm.c and
    > http://www.iedu.com/mrd/c/getsmx.c that deal with a similar situation.
    >
    > The two are functionally equivalent; but the second module "cheats" in
    > that it uses a gcc extension to allow embedding one function
    > declaration inside another. It's non-standard but may have some value
    > as a thought-provoking device.


    My, what large comment blocks you have. :-D

    I found a number of (even trivial) things thought-provoking. The
    imbedded function (getsmx.c) is outright trippy; it would have taken me
    a while just to find it without your comments marking its start and end,
    and even more time to figure out was going on.

    Where you comment like this:

    #include <stdio.h> /* fgetc() */

    I've been commenting in the reverse:

    fgetc(foo); /* <stdio.h> */

    I haven't yet noodled much with structures, nor braved malloc at all, so
    I'm a bit lost on how you entirely eliminated...

    typedef struct {...} getstr; /* getsm.c */

    ....from getsmx.c. Though I can see where the structure's contents moved
    to. I'll take another look after I get some sleep...

    Why have some local variables been explicitly declared with automatic
    storage duration?

    Having an #ifdef encapsulated "in-line" test main() is frickin' cool. I'll
    have to borrow this idea. ;-)

    I note you use **argv as a parameter to main() instead of the conventional
    *argv[]. I like that. The latter confused and frightened me when I was
    first learning pointers. Even now, the former seems clearer to me.

    I note also that you don't make use at all of argc. This made me laugh. I
    recently finished a program that made extensive use of **argv, but I
    couldn't find a use for argc. Everytime I re-compiled it I got the
    message:

    Warning: 'argc' initialized but never used.

    ....or some such. I contemplated putting in some dummy code just to make
    the warning go away. Does gcc not spit out a similar warning?


    Thank you most kindly for letting me peek inside your code.


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 20, 2006
    #5
  6. I.M. !Knuth

    I.M. !Knuth Guest

    Barry Schwarz <> wrote:

    > On Wed, 19 Jul 2006 06:33:14 +0000 (UTC), "I.M. !Knuth"
    > <> wrote:

    <snip>
    >>--> static int prev_pos; /* conveniently init'd to 0 on 1st call */

    >
    > Just a nit. Static variables are initialized prior to your program
    > beginning execution and independent of your function.


    D'oh! I knew that. Really, I did.


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 20, 2006
    #6
  7. I.M. !Knuth

    I.M. !Knuth Guest

    Keith Thompson <> wrote:

    > Barry Schwarz <> writes:
    >> On Wed, 19 Jul 2006 06:33:14 +0000 (UTC), "I.M. !Knuth"
    >> <> wrote:

    <snip>
    >>>--> static int prev_pos; /* conveniently init'd to 0 on 1st call */

    >>
    >> Just a nit. Static variables are initialized prior to your program
    >> beginning execution and independent of your function.

    >
    > True -- but, by the as-if rule, an implementation conceivably *could*
    > delay the initialization until the first call. (Nothing outside the
    > function can see the variable before that and detect that it hasn't
    > been initialized. Local static variables can be seen via pointers
    > outside the function that defines them, but there's no way to
    > initialize such a pointer before calling the function.)
    >
    > But I can't think of a good reason for an implementation to do such a
    > silly thing.


    So, hypothetically, I only look dumb under some implementation-specific
    circumstances. :-D

    BTW, what's the "as-if rule"?


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 20, 2006
    #7
  8. "I.M. !Knuth" <> writes:
    > Keith Thompson <> wrote:
    >> Barry Schwarz <> writes:
    >>> On Wed, 19 Jul 2006 06:33:14 +0000 (UTC), "I.M. !Knuth"
    >>> <> wrote:

    > <snip>
    >>>>--> static int prev_pos; /* conveniently init'd to 0 on 1st call */
    >>>
    >>> Just a nit. Static variables are initialized prior to your program
    >>> beginning execution and independent of your function.

    >>
    >> True -- but, by the as-if rule, an implementation conceivably *could*
    >> delay the initialization until the first call. (Nothing outside the
    >> function can see the variable before that and detect that it hasn't
    >> been initialized. Local static variables can be seen via pointers
    >> outside the function that defines them, but there's no way to
    >> initialize such a pointer before calling the function.)
    >>
    >> But I can't think of a good reason for an implementation to do such a
    >> silly thing.

    >
    > So, hypothetically, I only look dumb under some implementation-specific
    > circumstances. :-D


    Um, sure. :cool:}

    > BTW, what's the "as-if rule"?


    The general idea is that the standard describes the behavior of an
    abstract machine, but the actual generated code is allowed to behave
    differently as long as the result is *as if* it followed the semantics
    described in the standard. It allows for optimizations such as
    eliminating calculations whose results are never used.

    C99 5.1.2.2.3p3:

    In the abstract machine, all expressions are evaluated as
    specified by the semantics. An actual implementation need not
    evaluate part of an expression if it can deduce that its value is
    not used and that no needed side effects are produced (including
    any caused by calling a function or accessing a volatile object).

    C99 5.1.2.2.3p5:

    The least requirements on a conforming implementation are:

    -- At sequence points, volatile objects are stable in the sense
    that previous accesses are complete and subsequent accesses
    have not yet occurred.

    -- At program termination, all data written into files shall be
    identical to the result that execution of the program according
    to the abstract semantics would have produced.

    -- The input and output dynamics of interactive devices shall take
    place as specified in 7.19.3. The intent of these requirements
    is that unbuffered or line-buffered output appear as soon as
    possible, to ensure that prompting messages actually appear
    prior to a program waiting for input.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 20, 2006
    #8
  9. I.M. !Knuth

    jaysome Guest

    On Thu, 20 Jul 2006 06:29:49 +0000 (UTC), "I.M. !Knuth"
    <> wrote:

    >Keith Thompson <> wrote:
    >
    >> Barry Schwarz <> writes:
    >>> On Wed, 19 Jul 2006 06:33:14 +0000 (UTC), "I.M. !Knuth"
    >>> <> wrote:

    ><snip>
    >>>>--> static int prev_pos; /* conveniently init'd to 0 on 1st call */
    >>>
    >>> Just a nit. Static variables are initialized prior to your program
    >>> beginning execution and independent of your function.

    >>
    >> True -- but, by the as-if rule, an implementation conceivably *could*
    >> delay the initialization until the first call. (Nothing outside the
    >> function can see the variable before that and detect that it hasn't
    >> been initialized. Local static variables can be seen via pointers
    >> outside the function that defines them, but there's no way to
    >> initialize such a pointer before calling the function.)
    >>
    >> But I can't think of a good reason for an implementation to do such a
    >> silly thing.

    >
    >So, hypothetically, I only look dumb under some implementation-specific
    >circumstances. :-D
    >
    >BTW, what's the "as-if rule"?


    The intention was to provide direction through example. The examples
    were meant to be unambiguous. I think the committee achieved that for
    the most part.

    Best regards
    --
    jay
     
    jaysome, Jul 20, 2006
    #9
  10. jaysome <> writes:
    > On Thu, 20 Jul 2006 06:29:49 +0000 (UTC), "I.M. !Knuth"
    > <> wrote:

    [...]
    >>BTW, what's the "as-if rule"?

    >
    > The intention was to provide direction through example. The examples
    > were meant to be unambiguous. I think the committee achieved that for
    > the most part.


    Um, what does that have to with the "as-if" rule?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 20, 2006
    #10
  11. In article <Xns98055B40DA1711011011@81.174.50.80>, "I.M. !Knuth" <> writes:
    > A while back, I was mucking around with a recursive function. For
    > brevity's sake, I'll define it like this:
    >
    > int func_recurs(int arg1, int arg2, int prev_pos)
    > ...
    >
    > But written this way, I had to remember that any call to func_recurs()
    > always had to look like this:
    >
    > func_recurs(arg1, arg2, 0);
    >
    > Frankly, I thought that constant 0 dangling at the end was rather
    > inelegant. Then it struck me that maybe I could "hide" func_recurs
    > inside another function so that I wouldn't have to strain my brain
    > remembering about that pesky third argument; something like:
    >
    > func_lazymemory(int arg1, int arg2)
    > {
    > func_recurs(arg1, arg2, 0);
    > }
    >
    > Being new to C, I felt pretty clever for coming up with this all on my
    > own. But then I thought: "Bah! Smells of kludge. There must be a
    > better way."


    There are other ways, certainly. But this style - the recursive
    function that includes parameters for current state, and a wrapper
    that passes the initial state - is very common in functional
    programming. You'll often find it in programs written in Lisp, SML,
    and other functional languages.

    So it's a common idiom. I wouldn't consider it a kluge at all.

    One change I would make is to give func_recurs internal linkage (by
    adding the "static" sc-specifier), since the public interface to this
    operation is now func_lazymemory.

    --
    Michael Wojcik

    I would never understand our engineer. But is there anything in this world
    that *isn't* made out of words? -- Tawada Yoko (trans. Margaret Mitsutani)
     
    Michael Wojcik, Jul 21, 2006
    #11
  12. I.M. !Knuth

    Morris Dovey Guest

    My ISP is dropping over half of the clc postings. I took a quick look
    through Google's archive to see what I've missed and found IM!Knuth's
    reply with questions and comments. Sorry I'm so late responding.

    | My, what large comment blocks you have. :-D

    Deteriorating eyesight. They're easier for me to find if I draw a box
    around 'em. :)

    | I haven't yet noodled much with structures, nor braved malloc at
    all, so I'm
    | a bit lost on how you entirely eliminated...
    |
    | typedef struct {...} getstr; /* getsm.c */
    |
    | ...from getsmx.c. Though I can see where the structure's contents
    moved
    | to. I'll take another look after I get some sleep...

    The variables defined in the containing function are known in the
    contained function.

    | Why have some local variables been explicitly declared with
    automatic
    | storage duration?

    Good question. In writing/reading recursive functions it's generally a
    good idea to be aware of how much 'baggage' is being carried with each
    recursion. It's really just there to call attention to the fact that
    "here's some baggage".

    | Having an #ifdef encapsulated "in-line" test main() is frickin'
    cool. I'll
    | have to borrow this idea. ;-)

    Actually, it's laziness. It's a way for me to always have a unit test
    module handy when I need one - without having to remember where I
    saved it. It's also one more way for me to remind myself how I planned
    to use/invoke the function when I wrote it. I have a really powerful
    memory - but it's all short-term. :)

    | I note you use **argv as a parameter to main() instead of the
    conventional
    | *argv[]. I like that. The latter confused and frightened me when I
    was
    | first learning pointers. Even now, the former seems clearer to me.

    It's one of those "six of one, half dozen of the other" kinds of
    things. Probably an indicator that my wheels are in a rut.

    | I note also that you don't make use at all of argc. This made me
    laugh. I
    | recently finished a program that made extensive use of **argv, but I
    | couldn't find a use for argc. Everytime I re-compiled it I got the
    | message:
    |
    | Warning: 'argc' initialized but never used.
    |
    | ...or some such. I contemplated putting in some dummy code just to
    make
    | the warning go away. Does gcc not spit out a similar warning?

    I think so (no gcc on this machine) but you can pacify it by adding a
    statement (which is probably discarded during compilation) something
    like:

    (void) argc;

    | Thank you most kindly for letting me peek inside your code.

    You're entirely welcome. Most of that stuff came out of discussions
    here on clc and everything except 'snuf' is benign. The snuf program
    is a Linux executable used to kill the first instance of a process by
    name (rather than by PID number). It's handy for dealing with
    non-terminating loops and similar "oops!" situations.

    --
    Morris Dovey
    DeSoto Solar
    DeSoto, Iowa USA
    http://www.iedu.com/DeSoto
     
    Morris Dovey, Jul 21, 2006
    #12
  13. I.M. !Knuth

    I.M. !Knuth Guest

    Morris Dovey <> wrote:

    > My ISP is dropping over half of the clc postings. I took a quick look
    > through Google's archive to see what I've missed and found IM!Knuth's
    > reply with questions and comments. Sorry I'm so late responding.


    No apology necessary. As it happens, your predicament presents me with
    an opportunity to repay your kindness. My ISP has good completion but
    only 2 months retention. This has been annoying me greatly since I
    started following clc. I tried backtracking on Google, but (because my
    eyesight isn't worth writing home about either) enlarging the font size
    just causes those annoying ads to get in the way; so I searched around
    for a good free text server and found:

    news.cambrium.nl /* may I plug open NNTP servers here? */

    As of this post, it's got over 44,000 messages in clc dating back to mid
    October of last year with -- as far as I can tell -- rock solid
    completion. I've been reading off it for about a week now. Hope this
    helps you out. ;-)

    And now back to our program....

    <snip>
    >| ...I'm a bit lost on how you entirely eliminated...
    >|
    >| typedef struct {...} getstr; /* getsm.c */
    >|
    >| ...from getsmx.c. Though I can see where the structure's contents
    >| moved to. I'll take another look after I get some sleep...
    >
    > The variables defined in the containing function are known in the
    > contained function.


    Oh hey, I never noticed that ... and that isn't even the part that was
    messing with me. :-D

    >| Why have some local variables been explicitly declared with automatic
    >| storage duration?
    >
    > Good question. In writing/reading recursive functions it's generally a
    > good idea to be aware of how much 'baggage' is being carried with each
    > recursion. It's really just there to call attention to the fact that
    > "here's some baggage".


    Sound advice noted.

    <snip>

    Thanks again for broadening my horizons (even if ever so slightly).


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 22, 2006
    #13
  14. I.M. !Knuth

    I.M. !Knuth Guest

    I.M. !Knuth <> wrote:

    <snip>
    > ...so I searched around for a good free text server and found:
    >
    > news.cambrium.nl /* may I plug open NNTP servers here? */


    Oops! I should have added that it doens't allow posting.


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 22, 2006
    #14
  15. I.M. !Knuth

    I.M. !Knuth Guest

    Michael Wojcik <> wrote:

    <snip>
    >> ...I thought: "Bah! Smells of kludge. There must be a better way."

    >
    > There are other ways, certainly. But this style - the recursive
    > function that includes parameters for current state, and a wrapper
    > that passes the initial state - is very common in functional
    > programming. You'll often find it in programs written in Lisp, SML,
    > and other functional languages.
    >
    > So it's a common idiom. I wouldn't consider it a kluge at all.


    Cool. And reassuring. It felt like a kludge because it just seemed
    *too* easy. :)

    > One change I would make is to give func_recurs internal linkage (by
    > adding the "static" sc-specifier), since the public interface to this
    > operation is now func_lazymemory.


    Now here you had me scratching my head (and searching the FAQ).

    So if I read you correctly, your recommending that I define the
    functions like this:

    int func_lazymemory(int arg1, int arg2)
    { ... }

    ....and...

    int func_recurs(static int arg1, static int arg2, int prev_pos)
    { ... }

    ....so that storage will only be allocated once for both arg1 and arg2.
    Correct?

    If so, this handily provides and alternate answer to question 1b from my
    original post (which I just now noticed I bungled) where I was trying to
    pass pointers to conserve storage:

    /* Let the prototypes be: */

    int func_lazymemory(int, int);
    int func_recurs(int *, int *, int);


    /* And the definition of func_lazymemory() be */

    int func_lazy memory(int arg1, int arg2)
    {
    /* stuff happens, etc. */

    func_recurs(&arg1, &arg1, 0);

    return result;
    }

    Ultimately, this would have the same net effect, no?


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 22, 2006
    #15
  16. I.M. !Knuth

    I.M. !Knuth Guest

    Morris Dovey <> wrote:

    >| I note also that you don't make use at all of argc. This made me
    >| laugh. I recently finished a program that made extensive use of
    >| **argv, but I couldn't find a use for argc. Everytime I re-compiled
    >| it I got the message:
    >|
    >| Warning: 'argc' initialized but never used.
    >|
    >| ...or some such. I contemplated putting in some dummy code just to
    >| make the warning go away. Does gcc not spit out a similar warning?
    >
    > I think so (no gcc on this machine) but you can pacify it by adding a
    > statement (which is probably discarded during compilation) something
    > like:
    >
    > (void) argc;


    Just tried it, and yep, it does the trick. Casting to void never would
    have occurred to me.

    Thanks again.


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 22, 2006
    #16
  17. "I.M. !Knuth" <> writes:
    > Michael Wojcik <> wrote:

    [...]
    >> One change I would make is to give func_recurs internal linkage (by
    >> adding the "static" sc-specifier), since the public interface to this
    >> operation is now func_lazymemory.

    >
    > Now here you had me scratching my head (and searching the FAQ).
    >
    > So if I read you correctly, your recommending that I define the
    > functions like this:
    >
    > int func_lazymemory(int arg1, int arg2)
    > { ... }
    >
    > ...and...
    >
    > int func_recurs(static int arg1, static int arg2, int prev_pos)
    > { ... }
    >
    > ...so that storage will only be allocated once for both arg1 and arg2.
    > Correct?


    No, that's not even legal. He's suggesting that you make the
    *functions* static, not their parameters.

    int func_lazymemory(int arg1, int arg2)
    { ... }

    static int func_recurs(int arg1, int arg2, int prev_pos)
    { ... }

    The only effect of the "static" keyword here is that the function name
    "func_recurs" is not visible outside the current translation unit.
    (Making it more globally visible would probably be harmless, but it
    clutters the namespace.) There's no effect on allocation.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 22, 2006
    #17
  18. I.M. !Knuth

    I.M. !Knuth Guest

    Keith Thompson <> wrote:

    <snip>
    >> Now here you had me scratching my head (and searching the FAQ).
    >>
    >> So if I read you correctly, your recommending that I define the
    >> functions like this:
    >>
    >> int func_lazymemory(int arg1, int arg2)
    >> { ... }
    >>
    >> ...and...
    >>
    >> int func_recurs(static int arg1, static int arg2, int prev_pos)
    >> { ... }
    >>
    >> ...so that storage will only be allocated once for both arg1 and arg2.
    >> Correct?

    >
    > No, that's not even legal. He's suggesting that you make the
    > *functions* static, not their parameters.
    >
    > int func_lazymemory(int arg1, int arg2)
    > { ... }
    >
    > static int func_recurs(int arg1, int arg2, int prev_pos)
    > { ... }
    >


    D'oh! <slaps forehead>

    Thanks.

    > The only effect of the "static" keyword here is that the function name
    > "func_recurs" is not visible outside the current translation unit.
    > (Making it more globally visible would probably be harmless, but it
    > clutters the namespace.) There's no effect on allocation.


    So this *does* come down to Q1.29 in the FAQ. I skimmed over the
    namespace stuff to get to the "juicy bits" I thought pertained to me.
    I'll reread it more slowly. I better flip open K&R too. I thought
    "static" just kept a variable's storage alive within file scope. So by
    "the current translation unit" you mean inside the function wrapper?

    I'm so confused....


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 22, 2006
    #18
  19. [much apparently random snippage, in an attempt to clarify exactly what I'm
    answering and why]
    I.M. !Knuth said:
    > Keith Thompson <> wrote:
    >

    <snip>
    >>
    >> [...] He's suggesting that you make the *functions* static, not their
    >> parameters.
    >>
    >> int func_lazymemory(int arg1, int arg2)
    >> { ... }
    >>
    >> static int func_recurs(int arg1, int arg2, int prev_pos)
    >> { ... }
    >>

    [...]
    >> The only effect of the "static" keyword here is that the function name
    >> "func_recurs" is not visible outside the current translation unit. [...]


    > [...] I thought
    > "static" just kept a variable's storage alive within file scope. So by
    > "the current translation unit" you mean inside the function wrapper?


    No.

    Imagine a C source file. Got that? Just one. Now imagine that the C
    preprocessor has done its thing, and #included every #include it's been
    told about, recursively, until there is no more #including to be done. Once
    that's out of the way, we have a single unit of the program that is waiting
    to be translated. We call this a "translation unit". And so does the
    Standard. In the following quote from the Standard, I have marked off one
    sentence with *** *** marks because it is particularly relevant to you
    right now.


    2.1.1.1 Program structure

    A C program need not all be translated at the same time. The text
    of the program is kept in units called source files in this Standard.
    A source file together with all the headers and source files included
    via the preprocessing directive #include , less any source lines
    skipped by any of the conditional inclusion preprocessing directives,
    is called a translation unit. Previously translated translation units
    may be preserved individually or in libraries. ***The separate
    translation units of a program communicate by (for example) calls to
    functions whose identifiers have external linkage***, by manipulation of
    objects whose identifiers have external linkage, and by manipulation
    of data files. Translation units may be separately translated and
    then later linked to produce an executable program.


    If a function is static, it doesn't have external linkage, and can't be
    called-by-name from other translation units.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jul 22, 2006
    #19
  20. I.M. !Knuth

    I.M. !Knuth Guest

    Richard Heathfield <> wrote:

    <snip>
    > Imagine a C source file. Got that?....

    <snip>

    Ouch! You do carry a big stick, Sir.

    Yeah, I got it. For one thing, I was messing up my own definitions of
    global vs. static, and the FAQ's glossary filled me in on "translation
    unit". Upon re-reading, Mr. Thompson clearly stated everything I needed
    to know.

    It's getting into the wee hours in my time zone, and I've had a long
    day. I'd better just go sleep on it before I cause any more trouble.
    :)

    Thanks all, and g'night.


    --
    I.M. (definitely) !Knuth
     
    I.M. !Knuth, Jul 22, 2006
    #20
    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. Edwin Knoppert

    PInvoke, load library from desired folder?

    Edwin Knoppert, Nov 16, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    749
    Bruce Barker
    Nov 16, 2005
  2. .Net Sports
    Replies:
    2
    Views:
    371
    =?Utf-8?B?VG9tIEFuZGVyc29u?=
    Jan 20, 2006
  3. eJAYBee
    Replies:
    0
    Views:
    506
    eJAYBee
    Dec 10, 2004
  4. Matt
    Replies:
    1
    Views:
    492
    Whitecrest
    Jun 20, 2004
  5. Matt
    Replies:
    2
    Views:
    402
Loading...

Share This Page