Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Should I do that...? (http://www.velocityreviews.com/forums/t439395-should-i-do-that.html)

info@bitart.at 09-14-2005 09:30 AM

Should I do that...?
 
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 09-14-2005 09:42 AM

Re: Should I do that...?
 
info@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 09-14-2005 10:48 AM

Re: Should I do that...?
 
info@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 (irrwahn35@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

info@bitart.at 09-14-2005 11:45 AM

Re: Should I do that...?
 
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 09-14-2005 11:57 AM

Re: Should I do that...?
 
Lawrence Kirby <lknews@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 ...
--
Irrwahn Grausewitz (irrwahn35@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 09-14-2005 12:23 PM

Re: Should I do that...?
 
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

Martin Ambuhl 09-14-2005 04:28 PM

Re: Should I do that...?
 
info@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.

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


John Bode 09-14-2005 04:57 PM

Re: Should I do that...?
 

info@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.

> for ( i = 0; i < 3; i++ ) StartFunctions( v[i] );
> return 0;
> }



Tim Woodall 09-14-2005 07:38 PM

Re: Should I do that...?
 
On 14 Sep 2005 04:45:27 -0700,
info@bitart.at <info@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.

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 09-14-2005 07:54 PM

Re: Should I do that...?
 
Tim Woodall <devnull@woodall.me.uk> writes:
> On 14 Sep 2005 04:45:27 -0700,
> info@bitart.at <info@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) kst-u@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.


All times are GMT. The time now is 05:06 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.