Should I do that...?

I

info

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;
}
 
R

Richard Heathfield

(e-mail address removed) 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;
}
 
I

Irrwahn Grausewitz

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.
 
I

info

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
 
I

Irrwahn Grausewitz

Lawrence Kirby said:
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 ...
 
L

Lawrence Kirby

On Wed, 14 Sep 2005 12:48:07 +0200, Irrwahn Grausewitz wrote:

....
int main( void )


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
 
M

Martin Ambuhl

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;
}
 
J

John Bode

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;
}
 
T

Tim Woodall

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.
 
K

Keith Thompson

Tim Woodall said:
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.

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.)
 
S

Simon Biber

Irrwahn said:
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.
 
P

pete

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.
 
S

Simon Biber

pete said:
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.
 
W

Walter Roberson

pete wrote:
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.
 
E

Emmanuel Delahaye

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.
 
H

Huajian Luo

Emmanuel said:
(e-mail address removed) 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
 
S

Simon Biber

Huajian said:
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;
}
 

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

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top