Like Tree1Likes
  • 1 Post By laserlight

Arrays of function pointers

This is a discussion on Arrays of function pointers within the C Programming forums, part of the General Programming Boards category; I've been programming in C since the early 1980's, before C++ was invented. Back then computers weren't as fast as ...

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    3

    Arrays of function pointers

    I've been programming in C since the early 1980's, before C++ was invented.
    Back then computers weren't as fast as they are now so we had to make every line of code work hard. Did you know you can execute one element in an array of function pointers ? I use the tiny-C compiler so this is an entire program and cleanly compiles to a 1,536 byte executable.
    Here is some code for you to chew on (take this code and run with it);

    Code:
    int fn1(int), fn2(int);
        
    main()
    {
        int (*fnptr[2])(int);
        int i = 0;
        
        printf("Hello world!\n");
        fnptr[0] = &fn1;
        fnptr[1] = &fn2;
        
        while(i=(*fnptr[i])(i));
    }
    
    
    int fn1(int i)
    {
        printf("Hello world fn1 got %d!\n",i);
        return(1);
    }
    
    
    int fn2(int i)
    {
        printf("Hello world fn2 got %d!\n",i);
        return(0);
    }
    See if you can determine it's output before you compile & run it.
    If you put the functions before the main, you don't need the function declarations. We removed much of the white space to save on file size, it was an issue back then. We recognized ram in kilobytes, megabytes weren't really invented yet. I'm pretty sure you didn't want one long line.
    It's elegant in its simplicity. When I had thousands of functions to fulfill, I would write a program that would write the program I compiled. I could take 2 days writing the program or 2 hours writing a program that would write the program for me.

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,296
    Welcome newcomer!
    The printf's are outputted in the order of the one in main, then from fn1, then from fn2. Then the loop stops since zero was returned and the program terminates.

    Did you know you could also use the ternary operator like this?:
    Code:
    while(i = (i ? fn1 : fn2)(i));
    Are you also aware of modern C99 features such as variable length arrays? e.g.:
    Code:
    int len = 1;
    scanf("%d", &len);
    int array[len];
    Not meaning to insult, but if you stick around on the forums you'll find that there are probably plenty of those who probably know modern C even better than you do on here, despite your years of experience. That's because regular contributors on here undergo continuous improvement, through learning from the combined knowledge of everyone here. You'll see soon enough that a few years on here can teach you more than a few decades learning on your own. Seriously, this is where you come to stay ahead in the field!

    Note: You should declare main to return an int explicitly rather than letting it default to int.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,208
    Quote Originally Posted by iMalc View Post
    Not meaning to insult, but if you stick around on the forums you'll find that there are probably plenty of those who probably know modern C even better than you do on here, despite your years of experience.
    There is also a fair number of people here who are very familiar with the ancient style of C in the first post, as well as with modern C.

    Also not intending to insult, but there are better introductions into an active programming forum than code based on several techniques that were obsoleted over a decade ago.
    Right 98% of the time, and don't care about the other 3%.

  4. #4
    Registered User
    Join Date
    Oct 2012
    Posts
    3
    Quote Originally Posted by iMalc View Post

    Did you know you could also use the ternary operator like this?:
    Code:
    while(i = (i ? fn1 : fn2)(i));
    [/code]
    I compiled it and its the same size. Running it fn1 doesn't get called.
    Mine works with as many functions you code. Lets see you code with 6000 functions. The result of the function determines which function is called next. Very powerful and fast execution. Same concept is used in compiler design theory. I wanted to show that functions can be called dynamically determined by the last result of the previous function. Do you know of another compiler that can make such a tiny fully functional executable ? Ternary operators have their place and this isn't it. Yours has a test to determine which function to call next, mine just goes. Mine is immensely more efficient. Mine is dynamic, yours isn't.

  5. #5
    Registered User camel-man's Avatar
    Join Date
    Jan 2011
    Location
    Under the moon
    Posts
    593
    Quote Originally Posted by larmo View Post
    I compiled it and its the same size. Running it fn1 doesn't get called.
    Mine works with as many functions you code. Lets see you code with 6000 functions. The result of the function determines which function is called next. Very powerful and fast execution. Same concept is used in compiler design theory. I wanted to show that functions can be called dynamically determined by the last result of the previous function. Do you know of another compiler that can make such a tiny fully functional executable ? Ternary operators have their place and this isn't it. Yours has a test to determine which function to call next, mine just goes. Mine is immensely more efficient. Mine is dynamic, yours isn't.

    Name:  200px-Trollface.svg.png
Views: 140
Size:  12.1 KB

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,296
    Quote Originally Posted by larmo View Post
    I compiled it and its the same size. Running it fn1 doesn't get called.
    Mine works with as many functions you code. Lets see you code with 6000 functions. The result of the function determines which function is called next. Very powerful and fast execution. Same concept is used in compiler design theory. I wanted to show that functions can be called dynamically determined by the last result of the previous function. Do you know of another compiler that can make such a tiny fully functional executable ? Ternary operators have their place and this isn't it. Yours has a test to determine which function to call next, mine just goes. Mine is immensely more efficient. Mine is dynamic, yours isn't.
    That was not my point. I know it does not do the same thing. You are not showing me anything new here. I have used arrays of function pointers, and even function references, in C++ for years. e.g. My sorting demo program has an array of pointers to different sorting routines which is used in the test routines.

    My point is that you would be rather foolish to assume that you know more than others here, which you will find out soon enough. You never answered any of my questions either.

    I am not really interested in how you can produce a small exe with some particular compiler. If I were trying to produce say a 4K demo, then I would probably use a smaller CRT, e.g. "tinyCRT" if memory servers correctly, and that would likely produce an exe at least as small.
    Arrays of function pointers are a tool like any other, and are more about performance optimisation, and convenience, than size optimisation.

    By the way, the term used for a program that produces its own source as output is called a "quine". Assuming that's what you were referring to in your first post. Perhaps they didn't have a name for it back then?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,208
    Quote Originally Posted by larmo View Post
    I compiled it and its the same size. Running it fn1 doesn't get called.
    That's because iMalc ordered things wrong in the ternary expression. An easy/understandable error to make, easily detected, and easily fixed.

    IMalc's point that you are showing nothing new is also valid.
    Quote Originally Posted by larmo View Post
    Mine works with as many functions you code. Lets see you code with 6000 functions. The result of the function determines which function is called next.
    From a design perspective, it also requires each function to identify which function comes next. It is often easier to use a simple for loop. The logic of "what comes next" has to be somewhere.

    Quote Originally Posted by larmo View Post
    Very powerful and fast execution. Same concept is used in compiler design theory. I wanted to show that functions can be called dynamically determined by the last result of the previous function.
    Probably easier for the function to return a function pointer. That actually identifies the function to be called, rather than an index. It would actually be clearer, and no need for arrays at all. All a function needs to know is the name of what function it calls next.

    Your approach is also easily broken by a function that returns a bad index. Consider what happens if the array of function pointers has ten elements, but one of the functions returns an index of 10.

    Your approach requires a mapping to be kept straight (all functions return an int to a valid index). It also hard-codes meanings of integer values (say, that a value 37 means "print hello in German"). That might work if new functions are only ever added. It won't work if someone decides to remove one of the functions .... suddenly the meaning of an index (and all subsequent indexes) changes. That means your design is brittle to change.

    Quote Originally Posted by larmo View Post
    Do you know of another compiler that can make such a tiny fully functional executable ?
    As a matter of fact, I do. Executable size is a quality-of-implementation issue for compilers, and quite a few either default to small executables (like tiny C) or support options to minimise size (a lot of others).

    Tiny-C also achieves small executables by being very focused in what it targets (eg x86), and trades off performance to achieve small size. There is also the wrinkle that tiny C is no longer being actively maintained (unless someone has taken it up recently that I don't know about).
    Quote Originally Posted by larmo View Post
    Ternary operators have their place and this isn't it. Yours has a test to determine which function to call next, mine just goes. Mine is immensely more efficient. Mine is dynamic, yours isn't.
    Your program requires a test, it's just not as explicit as iMalc's example. And, however you do it, your approach requires each function to know about what function to be called next. Whether that is done by returning an int (your approach) or a function pointer (alternative I suggested above) that implies a tight coupling between functions. Such a design can be a a pig of a thing to maintain. The fact you rely on the order in which function pointers are ordered in the array makes your approach even more fragile to change.

    You also seem to believe efficiency is an absolute concept. It is not: efficiency is a relative concept, with various possible measures, and it is rare to find a program that is optimal against all measures. If you care about small executable size with the Tiny-C compiler, then fine. Most of us in the real world make a trade-off between various types of efficiency (compile time, executable size, runtime speed, programmer maintenance effort, etc etc).
    Last edited by grumpy; 10-13-2012 at 05:37 PM.
    Right 98% of the time, and don't care about the other 3%.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,456
    Dunno, this seems to be much ado about little.

    Quote Originally Posted by larmo
    Did you know you can execute one element in an array of function pointers ?
    Yes, that is exceedingly obvious. The less obvious idea would be that "the result of the function determines which function is called next", but as iMalc noted, it is certainly not unknown or new to most of us here.

    I think the reactions that you are getting in this thread is because you came in with a "I'm more experienced and smarter than you" attitude, which obviously does not win you fans or friends.

    Anyway, let's just move on. My suggestion is that if you want to post something like this that you think will benefit the community here, go ahead, but frame it such that you invite discussion and critique, rather than you "showing off". Other than that, feel free to join in the answering of questions and such around here. Welcome!
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Oct 2012
    Posts
    3
    Quote Originally Posted by grumpy View Post
    Your program requires a test, it's just not as explicit as iMalc's example.
    Can you point out where the test is ?
    I don't see any IF statements!

    For those that aren't familiar, look up "finite state processing".

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,456
    Quote Originally Posted by larmo
    Can you point out where the test is ?
    I don't see any IF statements!
    The while loop's condition.

    EDIT:
    That said, since iMalc's version also has such a while loop, it is kind of unfair to use that... but you did ask to point out where there was a test without specifying that you wanted to exclude the while loop's condition in the answer
    Last edited by laserlight; 10-14-2012 at 12:25 PM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    611
    Quote Originally Posted by larmo View Post
    Do you know of another compiler that can make such a tiny fully functional executable ?
    Visual Studio compiled in the picture (despite the folder name). Probably GCC, Clang and 'em can too. If that's your major goal, buddy you ain't even close.
    Name:  vs.png
Views: 107
Size:  41.9 KB

  12. #12
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by adeyblue View Post
    Visual Studio compiled in the picture (despite the folder name). Probably GCC, Clang and 'em can too. If that's your major goal, buddy you ain't even close.
    What settings did you use? I assume it's dynamically linked (is it?) whereas I got the impression that the OP's code was statically linked.

    EDIT: Actually, probably neither is statically linked.
    Last edited by oogabooga; 10-14-2012 at 08:13 PM.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,456
    Eh, the size of the executable is something of a red herring here. Stroustrup has an FAQ on a related note, and it applies here when considering Tiny C and other compilers. Yet, beyond trivial programs, the overhead bloat of an implementation that links to too much stuff would matter less and less as the actual code written increases.
    oogabooga likes this.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,184
    O_o

    How have you programmed "since the early 1980's" and never heard of table driven development?

    [Edit]
    There is also a fair number of people here who are very familiar with the ancient style of C in the first post, as well as with modern C.
    ^_^

    You know, I'm sorely tempted to post a bit of code doing the same thing but using "Boost:Proto".
    [/Edit]

    Soma
    Last edited by phantomotap; 10-14-2012 at 08:47 PM.

  15. #15
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,638
    I'm pretty sure the easiest way to confuse people on the board is to post obfuscated code.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 05-19-2010, 02:12 AM
  2. Storing function pointers in generic pointers
    By Boxknife in forum C Programming
    Replies: 6
    Last Post: 08-01-2009, 01:33 PM
  3. Passing pointers to arrays of char arrays
    By bobthebullet990 in forum C Programming
    Replies: 5
    Last Post: 03-31-2006, 04:31 AM
  4. arrays of pointers to function?????
    By andyzjk in forum C++ Programming
    Replies: 11
    Last Post: 04-17-2005, 09:55 AM
  5. Casting function pointers into char arrays and back
    By coolman0stress in forum C++ Programming
    Replies: 2
    Last Post: 07-05-2003, 01:50 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21