disgusting compiler !! hahaha!!

Discussion in 'C Programming' started by raj shekar, May 7, 2014.

  1. raj shekar

    Joe Pfeiffer Guest

    My experience, after spending my formative programming years in Pascal,
    is that nested functions are one of those ideas that sound cool but turn
    out to be nearly useless. Any of the versions of modules I've
    encountered (including C's compilation of separate files with 'static'
    meaning file scope) have been infinitely more useful in practice.
     
    Joe Pfeiffer, May 10, 2014
    #61
    1. Advertisements

  2. A file is a natural unit. So is a node in a call tree. So the C way
    of doing things is quite elegant.
    A nested / local function makes the enclosing function harder to read,
    and if it's allowed access to caller's local variables, it makes the
    state of the variables hard to follow. You've got to check that
    every call isn't modifying your loop counter.
    There's also the issue of too much indentation. In C, indentation
    represents either loop nesting level or alternative branching, so
    two meanings. If you add indentation for nested functions, then you've
    added another meaning, you've also blown up the number of indentations.
     
    Malcolm McLean, May 10, 2014
    #62
    1. Advertisements

  3. raj shekar

    Osmium Guest

    I remember when there was a guy at the gas station that not only put gas in
    your gas tank he washed your windshield too!
     
    Osmium, May 10, 2014
    #63
  4. raj shekar

    Jorgen Grahn Guest

    And the BASIC dialect I used briefly in the 80s had "OPTION BASE 0".
    (And now that I google it, I see that Microsoft have it too, in Visual
    Basic.)

    Anyway, in my part of the programming world origin 0 won a long time
    ago. All languages I'm likely to ever use do it that way.

    /Jorgen
     
    Jorgen Grahn, May 10, 2014
    #64
  5. raj shekar

    BartC Guest

    I have the same problem with nested directories on a disk drive.

    Maybe going from one level to two levels was a good idea, to separate out
    your projects.

    But going to N levels? I've spent endless amounts of time after downloading
    sources or applications trying to find where, for example, the include files
    happen to be! With most directories only containing .. one other directory.

    With one application, I've counted a maximum of 15 file levels:

    \Arduino\hardware\arduino\firmwares\wifishield\wifiHD\src\SOFTWARE_FRAMEWORK\SERVICES\LWIP\lwip-1.3.2\src\include\ipv4\lwip

    (Not including the root directory! And this is part of the support for a
    weedy little microprocessor too. Notice 'arduino' and 'src' twice each.
    Compiling any programs under this system -- there is a gcc compiler in the
    tree, in \Arduino\hardware\tools\avr\avr\bin, only 6 levels deep -- involves
    include paths up to 12 deep, many with repeated paths that include "." and
    "..", and up to three "avr" for good measure!)

    I think this is becoming like certain C include files: not designed to be
    human readable anymore (which is important when trying to make sense of this
    stuff from the outside). I'm not surprised there is so much bloatware when
    projects get so big and disorganised that people give up on them.

    Perhaps it's a good thing then that nested functions haven't really caught
    on.
     
    BartC, May 10, 2014
    #65
  6. raj shekar

    Walter Banks Guest

    I will answer this with more detail later but the function
    pointer in your example is the same as taking the pointer
    address of a variable and then referencing it out of scope.

    inner scope is limited to in your case the function
    outer.

    The point of nested functions is a function that has
    limited scope in the same way as local variables
    have limited scope.

    w..
     
    Walter Banks, May 10, 2014
    #66
  7. raj shekar

    Walter Banks Guest

    Nested functions are just a scoping issue both for use and implementation.
    Think of all of the expected expected restrictions on local variables.
    We can create pointers to local variables and use those pointers as
    long as the original variable is in scope. Inner functions can have
    pointers to as long as scope is respected. The scoping restriction
    can be an advantage for example function pointers with a sort.

    I have done implementations for both C compilers and and other
    languages for nested functions. I have not seen a particular problem
    or optimization problems during implementation. The nested function
    becomes part of the application structure and is dealt with as such.

    My usage experience is mostly using pascal where I have tended to
    use local functions a lot to isolate the logic of function implementation
    from the details. Maybe as many as half of the local functions were
    only called once in a function.

    w..
     
    Walter Banks, May 10, 2014
    #67
  8. Am 09.05.2014 20:41, schrieb Keith Thompson:
    Why? On a typical implementation on a typical CPU, such objects are
    placed on the hardware stack, along with the return address and (some or
    all) of the arguments of the called function. Since the stack frame of
    the calling function is known, and the stack frame of the called
    function is known, the objects of the calling function can be accessed
    from the called function just by an offset from the current stack frame,
    knowing the size of the objects on the stack. Thus, there is no overhead
    necessary.
    That seems to be necessary, i.e. function pointers to internal functions
    cannot be exported to the outside, unless the "inner function" does not
    refer to the stack frame of the calling function. (Such inner functions
    could be declared "static", i.e. then inner functions would just have
    internal linkage and their own name space).

    Greetings,
    Thomas
     
    Thomas Richter, May 11, 2014
    #68
  9. raj shekar

    David Brown Guest

    Thanks - that makes sense. To make the local function work, it needs a
    certain amount of context (pointers to local data, etc.). When you have
    an object, such as a lambda, that context can be part of the object -
    when you only have a standard function pointer, you need a trampoline.
     
    David Brown, May 11, 2014
    #69
  10. raj shekar

    David Brown Guest

    Yes, such limited local functions are easy to implement - but they are
    also of limited use. The only use they have is limited scope of the
    name, but since it is easy to get the same effect by using a normal
    static function and simply not calling it from other functions, it is
    not a big benefit. It would have some uses - just like function-local
    static variables - but the real power of local functions comes when you
    have access to the local variables of the surrounding scope.
     
    David Brown, May 11, 2014
    #70
  11. Even then, it shouldn't be so hard until you add recursion, but then
    C always allows recursion, so you have to handle it.

    You have to find the right stack frame for the appropriate instance
    of the calling function.

    This was all figured out when the first PL/I compiler was written,
    as the language was defined to allow it. Even more, PL/I allows
    for multitasking, so there could also be different tasks
    running the same function at the same time.

    -- glen
     
    glen herrmannsfeldt, May 11, 2014
    #71
  12. raj shekar

    BartC Guest

    I'm not sure why recursion comes into it. C functions will have local frame
    variables allocated on a stack whether recursive or not (they might be
    optimised out, but you can't depend on that).
    The problem is when you have function D inside C inside B inside A.

    You call A() which calls B() which calls C() which passes a pointer to D to
    some outside code.

    Later on, after A() has returned, a call is made directly to D().

    The problem now is that those locals belonging to A or B or C do not exist,
    yet D might try and reference them. Some of those locals might depend on
    parameters passed to A or B or C, so it can't just create suitable dummy
    locals to make do.

    (What D can access with no problem, is anything that isn't a local frame
    variable belonging to A or B or C: typedefs, constants (ideally, proper
    named constants that I've proposed elsewhere), static variables and enums.)
    I wonder why such a language never really took off?
     
    BartC, May 11, 2014
    #72
  13. raj shekar

    Walter Banks Guest

    The implementation I did was to essentially extend variable scoping. It
    potentially allowed local functions to be declared anywhere a local
    variable could be declared.

    The code in the local functions in my implementation had access to
    all variables in scope global or local to the host function. There
    are some interesting uses for local functions. They require language
    support and at this point C has some implementations of local function
    but the language doesn't support them. Years ago I did fly it by a
    WG-14 meeting and there was essentially no support for local
    functions to be added to the language.

    w..
     
    Walter Banks, May 11, 2014
    #73
  14. raj shekar

    Walter Banks Guest

    Recursion implementation in nested functions is mostly scope
    management.

    PL/I was one of those languages that was ahead of its time. It was
    developed about the same time as basic at a time when fortran was
    king.

    w..
     
    Walter Banks, May 11, 2014
    #74
  15. raj shekar

    Walter Banks Guest

    Good point, set vs range district ion. My pascal background is showing.
    The counter argument to your case 'A'..'Z' example is C applications
    are actually rarely ported. From a language point of view this is not a
    valid argument from an application developer point of view it is a very
    readable short cut.

    'A'..'Z' is clear the full english alphabet range and

    'A'..'K', 'M'..'Z' Christmas list is a lot clearer than the alternative.


    w..


    w..
     
    Walter Banks, May 11, 2014
    #75
  16. Or nested functions can call each other:

    void outer(void) {
    int foo;
    void inner1(void) {
    /* ... */
    }
    void inner2(void) {
    /* ... */
    }
    /* ... */
    }

    If inner1 refers to foo, it may have been called directly by
    outer (going up one level of stack frames) or by inner2 (going
    up two levels). Or it could have been called recursively, so
    you might have to search up the stack for an arbitrary number of
    levels before finding a stack frame that belongs to the innermost
    currently active call of outer (if the compiler uses a static link
    rather than a display).

    I don't suggest that this is an insurmountable problem (and it's
    already been solved for languages that have nested functions,
    and by gcc for its extended dialect of C), but it is non-trivial.

    As for using function pointers to call a nested function after its
    parent has terminated, that's not a major problem; it's similar to
    referring to local variables after the function that defines them
    has terminated. *If* nested function definitions were added to the
    language, I expect the standard would merely add a few words to say
    that such calls have undefined behavior. (A particular compiler
    might optionally add a check to detect such calls at run time and/or
    warn about the possibilty at compile time.) It would be simpler
    to say that *all* such calls have undefined behavior, whether the
    inner function refers to objects defined by its parent or not.

    But the committee has shown no particular interest in adding this
    to the language.
     
    Keith Thompson, May 11, 2014
    #76
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.