Should I do that...?

Discussion in 'C Programming' started by info@bitart.at, Sep 14, 2005.

  1. Guest

    Hello World,

    The code below compiles without warnings and the resulting program runs
    without any error.

    ....somehow I am not sure if I should do something like this and/or if
    there are any dangers...

    Any comments?

    #include <stdio.h>

    void Func1()
    {
    printf("func1\n");
    return;
    }

    void Func2()
    {
    printf("func2\n");
    return;
    }

    void Func3()
    {
    printf("func3\n");
    return;
    }

    void StartFunctions( void (*f)(void) )
    {
    printf("Starting Function...\n");
    f();
    return;
    }

    int main()
    {
    char i;
    void *v[] = { (void*)Func1, (void*)Func2, (void*)Func3 };
    for ( i = 0; i < 3; i++ ) StartFunctions( v );
    return 0;
    }
     
    , Sep 14, 2005
    #1
    1. Advertising

  2. said:

    > Hello World,
    >
    > The code below compiles without warnings and the resulting program runs
    > without any error.
    >
    > ...somehow I am not sure if I should do something like this and/or if
    > there are any dangers...
    >
    > Any comments?


    Although it is a common extension, the conversion between function pointers
    and void pointers is not guaranteed by the Standard to be lossless. I have
    corrected that problem in your code, below. I have also introduced a
    typedef, since it makes the whole thing easier to read, and added a couple
    of comments which I recommend that you read.

    #include <stdio.h>

    typedef void VFUNCV(void);

    void Func1(void)
    {
    printf("func1\n");
    return;
    }

    void Func2(void)
    {
    printf("func2\n");
    return;
    }

    void Func3(void)
    {
    printf("func3\n");
    return;
    }

    void StartFunctions( VFUNCV *f )
    {
    printf("Starting Function...\n");
    f(); /* I would prefer (*f)(); on the grounds that it reminds
    * us a function pointer is being used here. Either works.
    */
    return;
    }

    int main()
    {
    char i; /* Why char? What are you trying to save, and why? */
    VFUNCV *v[] = { Func1, Func2, Func3 };
    for ( i = 0; i < 3; i++ ) StartFunctions( v );
    return 0;
    }


    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/2005
    http://www.cpax.org.uk
    email: rjh at above domain
     
    Richard Heathfield, Sep 14, 2005
    #2
    1. Advertising

  3. wrote:
    >Hello World,
    >
    >The code below compiles without warnings and the resulting program runs
    >without any error.
    >
    >...somehow I am not sure if I should do something like this and/or if
    >there are any dangers...
    >
    >Any comments?


    See below.

    >#include <stdio.h>
    >
    >void Func1()


    Change this to:

    void Func1( void )

    to match the pointer declarations below.

    >{
    > printf("func1\n");
    > return;
    >}
    >
    >void Func2()


    Same here.

    >{
    > printf("func2\n");
    > return;
    >}
    >
    >void Func3()


    Same here.

    >{
    > printf("func3\n");
    > return;
    >}
    >
    >void StartFunctions( void (*f)(void) )
    >{
    > printf("Starting Function...\n");
    > f();
    > return;
    >}
    >
    >int main()


    This isn't one of the two legitimate declarations of main, use:

    int main( void )

    >{
    > char i;


    Using a character value for array subscripting is at least suspicious;
    no, wait, it's actually a constraint violation. Use:

    int i;

    > void *v[] = { (void*)Func1, (void*)Func2, (void*)Func3 };


    In order to avoid pointer type mismatches you presumably want:

    void (*v[])(void) = { Func1, Func2, Func3 };

    Note: cluttering your code with spurious casts is the wrong approach.
    Better use correct declarations in the first place.

    > for ( i = 0; i < 3; i++ ) StartFunctions( v );


    Minor quibble: beware of magic numbers (3).

    > return 0;


    That's fine. :eek:)

    >}


    HTH
    Best regards.
    --
    Irrwahn Grausewitz ()
    welcome to clc : http://www.ungerhu.com/jxh/clc.welcome.txt
    clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
    clc frequent answers: http://benpfaff.org/writings/clc
     
    Irrwahn Grausewitz, Sep 14, 2005
    #3
  4. Guest

    Dear Richard,

    thank you for your corrections

    char i; /* Why char? What are you trying to save, and why? */

    That was one of my questions. I wonder if I save _any_ memory by using
    char instead of int.
    The target of my application is a microcontroller where I really need
    to save memory. The application will be compiled with 1 byte alignment.

    yours,

    Herwig
     
    , Sep 14, 2005
    #4
  5. Lawrence Kirby <> wrote:
    >On Wed, 14 Sep 2005 12:48:07 +0200, Irrwahn Grausewitz wrote:

    <snip>
    >> Using a character value for array subscripting is at least suspicious;
    >> no, wait, it's actually a constraint violation. Use:
    >>
    >> int i;

    >
    >That is better, however you can use any integer type for an array
    >subscript (or more specifically pointer arithemtic) and character types
    >are perfectly good integer types.


    </me slaps forehead> Argh, I did it again. Note to self:

    I shall not read the standard hastily.
    I shall not read the standard hastily.
    I shall not ...
    --
    Irrwahn Grausewitz ()
    welcome to clc : http://www.ungerhu.com/jxh/clc.welcome.txt
    clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
    clc frequent answers: http://benpfaff.org/writings/clc
     
    Irrwahn Grausewitz, Sep 14, 2005
    #5
  6. On Wed, 14 Sep 2005 12:48:07 +0200, Irrwahn Grausewitz wrote:

    ....

    > int main( void )
    >
    >>{
    >> char i;

    >
    > Using a character value for array subscripting is at least suspicious;
    > no, wait, it's actually a constraint violation. Use:
    >
    > int i;


    That is better, however you can use any integer type for an array
    subscript (or more specifically pointer arithemtic) and character types
    are perfectly good integer types.

    >> void *v[] = { (void*)Func1, (void*)Func2, (void*)Func3 };

    >
    > In order to avoid pointer type mismatches you presumably want:
    >
    > void (*v[])(void) = { Func1, Func2, Func3 };
    >
    > Note: cluttering your code with spurious casts is the wrong approach.
    > Better use correct declarations in the first place.
    >
    >> for ( i = 0; i < 3; i++ ) StartFunctions( v );


    This would also have been an error in the original code, you cannot
    convert from void * to a funciton pointer type without a cast.

    Lawrence
     
    Lawrence Kirby, Sep 14, 2005
    #6
  7. wrote:
    > Hello World,
    >
    > The code below compiles without warnings and the resulting program runs
    > without any error.


    Then either you have an unhelpful compiler or you have your diagnostics
    incorrectly set. I get, for example

    a.c: In function 'main':
    a.c:42: warning: ISO C forbids conversion of function pointer to object
    pointer type
    a.c:42: warning: ISO C forbids conversion of function pointer to object
    pointer type
    a.c:42: warning: ISO C forbids conversion of function pointer to object
    pointer type
    a.c:44: warning: array subscript has type 'char'
    a.c:44: warning: ISO C forbids passing argument 1 of 'StartFunctions'
    between function pointer and 'void *'

    To fix this is easy. Change
    > void *v[] = { (void*)Func1, (void*)Func2, (void*)Func3 };

    to
    void (*v[])() = { Func1, Func2, Func3 };


    > ...somehow I am not sure if I should do something like this and/or if
    > there are any dangers...


    Of course there are dangers in writing broken code.

    >
    > Any comments?
    >
    > #include <stdio.h>
    >
    > void Func1()
    > {
    > printf("func1\n");
    > return;
    > }
    >
    > void Func2()
    > {
    > printf("func2\n");
    > return;
    > }
    >
    > void Func3()
    > {
    > printf("func3\n");
    > return;
    > }
    >
    > void StartFunctions( void (*f)(void) )
    > {
    > printf("Starting Function...\n");
    > f();
    > return;
    > }
    >
    > int main()
    > {
    > char i;
    > void *v[] = { (void*)Func1, (void*)Func2, (void*)Func3 };
    > for ( i = 0; i < 3; i++ ) StartFunctions( v );
    > return 0;
    > }
    >
     
    Martin Ambuhl, Sep 14, 2005
    #7
  8. John Bode Guest

    wrote:
    > Hello World,
    >
    > The code below compiles without warnings and the resulting program runs
    > without any error.
    >
    > ...somehow I am not sure if I should do something like this and/or if
    > there are any dangers...
    >
    > Any comments?
    >
    > #include <stdio.h>
    >
    > void Func1()


    /*
    ** make sure function prototypes match
    ** the prototype in StartFunctions
    */
    void Func1(void)

    > {
    > printf("func1\n");
    > return;
    > }
    >
    > void Func2()


    void Func2(void)

    > {
    > printf("func2\n");
    > return;
    > }
    >
    > void Func3()


    void Func3(void)

    > {
    > printf("func3\n");
    > return;
    > }
    >
    > void StartFunctions( void (*f)(void) )
    > {
    > printf("Starting Function...\n");
    > f();
    > return;
    > }
    >
    > int main()
    > {
    > char i;
    > void *v[] = { (void*)Func1, (void*)Func2, (void*)Func3 };


    void (*v[])(void) = {Func1, Func2, Func3};

    Converting between object and function pointers is bad juju.

    > for ( i = 0; i < 3; i++ ) StartFunctions( v );
    > return 0;
    > }
     
    John Bode, Sep 14, 2005
    #8
  9. Tim Woodall Guest

    On 14 Sep 2005 04:45:27 -0700,
    <> wrote:
    > Dear Richard,
    >
    > thank you for your corrections
    >
    > char i; /* Why char? What are you trying to save, and why? */
    >
    > That was one of my questions. I wonder if I save _any_ memory by using
    > char instead of int.
    > The target of my application is a microcontroller where I really need
    > to save memory. The application will be compiled with 1 byte alignment.
    >

    Depends on the compiler. Some compilers for 8 bit microcontrollers also
    include an option to make int 8 bits.

    You may also find that this is one place where register might make a
    difference.

    Tim.

    --
    God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
    and there was light.

    http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/
     
    Tim Woodall, Sep 14, 2005
    #9
  10. Tim Woodall <> writes:
    > On 14 Sep 2005 04:45:27 -0700,
    > <> wrote:
    >> Dear Richard,
    >>
    >> thank you for your corrections
    >>
    >> char i; /* Why char? What are you trying to save, and why? */
    >>
    >> That was one of my questions. I wonder if I save _any_ memory by using
    >> char instead of int.
    >> The target of my application is a microcontroller where I really need
    >> to save memory. The application will be compiled with 1 byte alignment.
    >>

    > Depends on the compiler. Some compilers for 8 bit microcontrollers also
    > include an option to make int 8 bits.


    This is, of course, non-conforming; int is required to be able to hold
    values in the range -32767 .. +32767. (But "non-conforming" is not
    synonymous with "evil"; there's nothing wrong with creating an
    implementation for something that's not quite C, as long as you don't
    claim that it conforms to the C standard.)

    --
    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, Sep 14, 2005
    #10
  11. Simon Biber Guest

    Irrwahn Grausewitz wrote:
    > wrote:
    >>int main()

    >
    > This isn't one of the two legitimate declarations of main, use:
    >
    > int main( void )


    The standard requires main to be defined with a type equivalent to one
    of the two legitimate declarations. The OP's definition is equivalent,
    and so perfectly valid.

    To make it clear: leaving out the "void" in the parameter list of a
    function _definition_ makes no difference. Leaving it out in a
    _declaration_ does make a difference.

    --
    Simon.
     
    Simon Biber, Sep 16, 2005
    #11
  12. pete Guest

    Simon Biber wrote:

    > To make it clear: leaving out the "void" in the parameter list of a
    > function _definition_ makes no difference. Leaving it out in a
    > _declaration_ does make a difference.


    Function definitions are also declarations.

    --
    pete
     
    pete, Sep 16, 2005
    #12
  13. Simon Biber Guest

    pete wrote:
    > Simon Biber wrote:
    >>To make it clear: leaving out the "void" in the parameter list of a
    >>function _definition_ makes no difference. Leaving it out in a
    >>_declaration_ does make a difference.

    >
    > Function definitions are also declarations.


    True, but this only matters if you're going to call the function from a
    subsequent function.

    As I was talking about the definition of the main function, this is
    something which, hopefully, no-one does in practice.

    --
    Simon.
     
    Simon Biber, Sep 16, 2005
    #13
  14. In article <432a5366$0$22808$>,
    Simon Biber <> wrote:
    >pete wrote:


    >> Function definitions are also declarations.


    >True, but this only matters if you're going to call the function from a
    >subsequent function.


    >As I was talking about the definition of the main function, this is
    >something which, hopefully, no-one does in practice.


    clc often has examples of people calling main recursively
    (at, at the very least, cursedly.)

    I wouldn't expect calling recursing to main to be -common-, but
    it apparently does happen in real life.
    --
    This signature intentionally left... Oh, darn!
     
    Walter Roberson, Sep 16, 2005
    #14
  15. Guest

    > Of course there are dangers in writing broken code.
    I'll gonna tell this my predecessor :)
     
    , Sep 16, 2005
    #15
  16. wrote on 14/09/05 :
    > Hello World,
    >
    > The code below compiles without warnings and the resulting program runs
    > without any error.


    Get a better compiler or learn how to tune it..

    main.c:8: warning: function declaration isn't a prototype
    main.c:14: warning: function declaration isn't a prototype
    main.c:20: warning: function declaration isn't a prototype

    main.c:26: warning: no previous prototype for 'StartFunctions'

    main.c: In function `main_':
    main.c:36: warning: array subscript has type `char'

    > ...somehow I am not sure if I should do something like this and/or if
    > there are any dangers...


    #include <stdio.h>

    typedef void Tfun (void);

    static void Func1 (void)
    {
    printf ("func1\n");
    return;
    }

    static void Func2 (void)
    {
    printf ("func2\n");
    return;
    }

    static void Func3 (void)
    {
    printf ("func3\n");
    return;
    }

    static void StartFunctions (void (*f) (void))
    {
    printf ("Starting Function...\n");
    f ();
    return;
    }

    int main (void)
    {
    size_t i;
    Tfun *v[] =
    {
    Func1,
    Func2,
    Func3,
    };

    for (i = 0; i < 3; i++)
    {
    StartFunctions (v);
    }
    return 0;
    }

    --
    Emmanuel
    The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
    The C-library: http://www.dinkumware.com/refxc.html

    "Mal nommer les choses c'est ajouter du malheur au
    monde." -- Albert Camus.
     
    Emmanuel Delahaye, Sep 17, 2005
    #16
  17. Huajian Luo Guest

    Emmanuel Delahaye wrote:
    > wrote on 14/09/05 :
    > int main (void)
    > {
    > size_t i;
    > Tfun *v[] =
    > {
    > Func1,
    > Func2,
    > Func3,
    > };
    >
    > for (i = 0; i < 3; i++)
    > {
    > StartFunctions (v);
    > }
    > return 0;
    > }

    I'm just curious about How can I traverse the array V with pointer,
    I've tried something like
    VFUNCV *p;
    for (p = *v; *p; p++) StartFunctions(*p);

    but that result core dump, Any hints to make it by poniter,
    Thanks,
    whatluo
     
    Huajian Luo, Oct 11, 2005
    #17
  18. Simon Biber Guest

    Huajian Luo wrote:
    > I'm just curious about How can I traverse the array V with pointer,
    > I've tried something like
    > VFUNCV *p;
    > for (p = *v; *p; p++) StartFunctions(*p);
    >
    > but that result core dump, Any hints to make it by poniter,


    #include <stdio.h>

    typedef void VFUNCV(void);

    void func1(void)
    {
    printf("func1\n");
    }

    void func2(void)
    {
    printf("func2\n");
    }

    void func3(void)
    {
    printf("func3\n");
    }

    VFUNCV *array[] =
    {
    func1,
    func2,
    func3
    };

    int main(void)
    {
    VFUNCV **p;
    VFUNCV **end = array + sizeof array / sizeof *array;

    for(p = array; p != end; ++p)
    {
    (*p)();
    }

    return 0;
    }

    --
    Simon.
     
    Simon Biber, Oct 13, 2005
    #18
    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. Mathew George
    Replies:
    1
    Views:
    2,382
  2. CM
    Replies:
    1
    Views:
    508
    Ed Kaim [MSFT]
    Oct 14, 2003
  3. ~~~ .NET Ed ~~~

    How should control images should be handled?

    ~~~ .NET Ed ~~~, Oct 31, 2004, in forum: ASP .Net Building Controls
    Replies:
    1
    Views:
    254
    John Saunders
    Nov 3, 2004
  4. Josef 'Jupp' SCHUGT

    What the FAQs should and should not contain

    Josef 'Jupp' SCHUGT, Aug 19, 2005, in forum: Ruby
    Replies:
    0
    Views:
    206
    Josef 'Jupp' SCHUGT
    Aug 19, 2005
  5. botp
    Replies:
    6
    Views:
    231
    Joel VanderWerf
    Oct 5, 2010
Loading...

Share This Page