Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Should I do that...?

Reply
Thread Tools

Should I do that...?

 
 
info@bitart.at
Guest
Posts: n/a
 
      09-14-2005
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;
}

 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      09-14-2005
http://www.velocityreviews.com/forums/(E-Mail 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[i] );
return 0;
}


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/2005
http://www.cpax.org.uk
email: rjh at above domain
 
Reply With Quote
 
 
 
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      09-14-2005
(E-Mail Removed) 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. )

>}


HTH
Best regards.
--
Irrwahn Grausewitz ((E-Mail Removed))
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
 
Reply With Quote
 
info@bitart.at
Guest
Posts: n/a
 
      09-14-2005
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

 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      09-14-2005
Lawrence Kirby <(E-Mail Removed)> 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 ((E-Mail Removed))
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
 
Reply With Quote
 
Lawrence Kirby
Guest
Posts: n/a
 
      09-14-2005
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
 
Reply With Quote
 
Martin Ambuhl
Guest
Posts: n/a
 
      09-14-2005
(E-Mail Removed) 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;
> }
>

 
Reply With Quote
 
John Bode
Guest
Posts: n/a
 
      09-14-2005

(E-Mail Removed) 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;
> }


 
Reply With Quote
 
Tim Woodall
Guest
Posts: n/a
 
      09-14-2005
On 14 Sep 2005 04:45:27 -0700,
(E-Mail Removed) <(E-Mail Removed)> 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/
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-14-2005
Tim Woodall <(E-Mail Removed)> writes:
> On 14 Sep 2005 04:45:27 -0700,
> (E-Mail Removed) <(E-Mail Removed)> 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) (E-Mail Removed) <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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
gems should *not be case sensitive.. or should they? botp Ruby 6 10-04-2010 11:42 PM
What the FAQs should and should not contain Josef 'Jupp' SCHUGT Ruby 0 08-19-2005 01:46 PM
Should I Bridge? =?Utf-8?B?Zmx1ZmZ5IHRoZSB3b25kZXIga2l0dGVu?= Wireless Networking 1 07-21-2005 01:25 AM
taking 70-290 should i be scared? What should i expect??? Raymond Munyan MCSE 31 12-01-2004 02:34 PM
How should control images should be handled? ~~~ .NET Ed ~~~ ASP .Net Building Controls 1 11-03-2004 12:30 PM



Advertisments