Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Should I do that...?

3 views
Skip to first unread message

in...@bitart.at

unread,
Sep 14, 2005, 5:30:01 AM9/14/05
to
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[i] );
return 0;
}

Richard Heathfield

unread,
Sep 14, 2005, 5:42:53 AM9/14/05
to
in...@bitart.at 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[i] );
return 0;
}


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/2005
http://www.cpax.org.uk
email: rjh at above domain

Irrwahn Grausewitz

unread,
Sep 14, 2005, 6:48:07 AM9/14/05
to
in...@bitart.at 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[i] );

Minor quibble: beware of magic numbers (3).

> return 0;

That's fine. :o)

>}

HTH
Best regards.
--
Irrwahn Grausewitz (irrw...@freenet.de)
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

Lawrence Kirby

unread,
Sep 14, 2005, 8:23:06 AM9/14/05
to
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[i] );

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

in...@bitart.at

unread,
Sep 14, 2005, 7:45:27 AM9/14/05
to
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

Irrwahn Grausewitz

unread,
Sep 14, 2005, 7:57:34 AM9/14/05
to
Lawrence Kirby <lkn...@netactive.co.uk> 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 ...

Martin Ambuhl

unread,
Sep 14, 2005, 12:28:42 PM9/14/05
to
in...@bitart.at 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.

John Bode

unread,
Sep 14, 2005, 12:57:13 PM9/14/05
to

in...@bitart.at 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.

Tim Woodall

unread,
Sep 14, 2005, 3:38:55 PM9/14/05
to
On 14 Sep 2005 04:45:27 -0700,
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/

Keith Thompson

unread,
Sep 14, 2005, 3:54:37 PM9/14/05
to
Tim Woodall <dev...@woodall.me.uk> writes:
> On 14 Sep 2005 04:45:27 -0700,
> in...@bitart.at <in...@bitart.at> 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) ks...@mib.org <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.

Simon Biber

unread,
Sep 15, 2005, 10:42:14 PM9/15/05
to
Irrwahn Grausewitz wrote:

> in...@bitart.at 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.

pete

unread,
Sep 15, 2005, 11:42:16 PM9/15/05
to
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

Simon Biber

unread,
Sep 16, 2005, 1:08:54 AM9/16/05
to

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.

Walter Roberson

unread,
Sep 16, 2005, 1:17:42 PM9/16/05
to
In article <432a5366$0$22808$afc3...@news.optusnet.com.au>,
Simon Biber <ne...@ralmin.cc> 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!

in...@bitart.at

unread,
Sep 16, 2005, 3:00:37 PM9/16/05
to
> Of course there are dangers in writing broken code.
I'll gonna tell this my predecessor :)

Emmanuel Delahaye

unread,
Sep 17, 2005, 6:06:18 PM9/17/05
to
in...@bitart.at 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[i]);
}
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.


Huajian Luo

unread,
Oct 11, 2005, 2:58:43 AM10/11/05
to
Emmanuel Delahaye wrote:
> in...@bitart.at wrote on 14/09/05 :

> int main (void)
> {
> size_t i;
> Tfun *v[] =
> {
> Func1,
> Func2,
> Func3,
> };
>
> for (i = 0; i < 3; i++)
> {
> StartFunctions (v[i]);
> }
> 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

Simon Biber

unread,
Oct 13, 2005, 1:57:01 PM10/13/05
to
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.

0 new messages