944,047 Members | Top Members by Rank

Ad:
  • C Discussion Thread
  • Marked Solved
  • Views: 1001
  • C RSS
You are currently viewing page 1 of this multi-page discussion thread
Nov 7th, 2009
0

Could Someone Try Compiling This On A Different Compiler

Expand Post »
I wrote this very small program that works fine until I remove the comments for the fprintf function.

Basically the program will prompt the user for a numeric value, when the user guesses right(1234) the program exits. When I remove the comments the program never exits...Does anyone have any idea why? I'm completely lost as to why it would behave like this...maybe its my compiler - gcc 4.4.1

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. unsigned long testval = 1234;
  5.  
  6. void* foundit(void)
  7. {
  8. fputs("found it!\n", stdout);
  9. return (void*)0;
  10. }
  11.  
  12. void* tryit(void)
  13. {
  14. unsigned long val;
  15.  
  16. fputs("enter a value/guess->", stdout);
  17. fscanf(stdin, "%u", &val);
  18.  
  19. if (val == testval)
  20. {
  21. return (void*)&foundit;
  22. }
  23. else
  24. {
  25. return (void*)&tryit;
  26. }
  27. }
  28.  
  29. int main(int argc, char**argv)
  30. {
  31. void *addr = (void*)&tryit;
  32.  
  33. //fprintf(stdout, "ans->%u\n", 1); //remove comments and program runs
  34. //but fails to exit with correct value
  35. while ((addr = ((void*(*)(void))addr)()))
  36. {}
  37. exit(EXIT_SUCCESS);
  38. }
Similar Threads
Reputation Points: 499
Solved Threads: 367
Postaholic
gerard4143 is online now Online
2,197 posts
since Jan 2008
Nov 7th, 2009
-7
Re: Could Someone Try Compiling This On A Different Compiler
>>while ((addr = ((void*(*)(void))addr)())

Didn't your compiler produce an error or warning on that line?? tryit() does not return a value, yet in the above addr is being assigned the return value of tryint(). You can't have it both ways. try this:
while( addr() )
Sponsor
Team Colleague
Featured Poster
Reputation Points: 5608
Solved Threads: 2282
Retired and Enjoying Life
Ancient Dragon is offline Offline
21,954 posts
since Aug 2005
Nov 7th, 2009
0
Re: Could Someone Try Compiling This On A Different Compiler
>>while ((addr = ((void*(*)(void))addr)())

Didn't your compiler produce an error or warning on that line?? tryit() does not return a value, yet in the above addr is being assigned the return value of tryint(). You can't have it both ways. try this:
while( addr() )
No the complier had no problems casting a void pointer to a function..should it?
And for tryit() the if statement assures that the function returns a value..

But that isn't the problem...The problem is when I remove the comments from this line

  1. //fprintf(stdout, "ans->%u\n", 1);

The program fails to exit correctly...Note the program works as intended while the comments are there...
Reputation Points: 499
Solved Threads: 367
Postaholic
gerard4143 is online now Online
2,197 posts
since Jan 2008
Nov 7th, 2009
-7
Re: Could Someone Try Compiling This On A Different Compiler
Worked fine for me using vc++ 2008 express
Quote ...
ans->1
enter a value/guess->1234
found it!
Press any key to continue . . .
Sponsor
Team Colleague
Featured Poster
Reputation Points: 5608
Solved Threads: 2282
Retired and Enjoying Life
Ancient Dragon is offline Offline
21,954 posts
since Aug 2005
Nov 7th, 2009
0
Re: Could Someone Try Compiling This On A Different Compiler
Worked fine for me using vc++ 2008 express
Humph...That means I'm going have to walk through some assembler and find out why removing the comments from this line

  1. fprintf(stdout, "ans->%u\n", 1);

causes the program to behave differently...well besides printing 1 to the display..

Thanks for trying the program Ancient Dragon
Reputation Points: 499
Solved Threads: 367
Postaholic
gerard4143 is online now Online
2,197 posts
since Jan 2008
Nov 7th, 2009
-7
Re: Could Someone Try Compiling This On A Different Compiler
>>well besides printing 1 to the display..

The reason for that should be obvious.

Also compiled with Code::Blocks using MinGW (gcc 3.4.5) and it worked ok.
Last edited by Ancient Dragon; Nov 7th, 2009 at 9:38 pm.
Sponsor
Team Colleague
Featured Poster
Reputation Points: 5608
Solved Threads: 2282
Retired and Enjoying Life
Ancient Dragon is offline Offline
21,954 posts
since Aug 2005
Nov 8th, 2009
0
Re: Could Someone Try Compiling This On A Different Compiler
Well I tried compiling the code on GCC 4.3.2 and it worked. I think GCC 4.4.1 may be in need of an update...Thanks again Ancient Dragon

So to recap:

the code will not work correctly on GCC 4.4.1
but it will work correctly on GCC 4.3.2, GCC 3.4.5 and vc++ 2008 express
Reputation Points: 499
Solved Threads: 367
Postaholic
gerard4143 is online now Online
2,197 posts
since Jan 2008
Nov 8th, 2009
2
Re: Could Someone Try Compiling This On A Different Compiler
>No the complier had no problems casting a void pointer to a function..should it?
It might. Technically void* and functions pointers are incompatible and converting between them is undefined behavior. I've seen compilers give both warnings and errors for such a conversion. The good news is that you can avoid this problem entirely by taking advantage of the fact that any function pointer type can be converted to any other function pointer type and back with well defined behavior (provided you call the function pointer with the correct type):
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. unsigned long testval = 1234;
  5.  
  6. /*
  7. Define a generic function pointer
  8. type for temporary conversion
  9. */
  10. typedef void (*func_t)(void);
  11.  
  12. /*
  13. Define a null value with the
  14. generic function pointer type
  15. */
  16. void null_func(void) { }
  17.  
  18. func_t foundit(void)
  19. {
  20. fputs("found it!\n", stdout);
  21. return null_function; /* No cast needed */
  22. }
  23.  
  24. func_t tryit(void)
  25. {
  26. unsigned long val;
  27.  
  28. fputs("enter a value/guess->", stdout);
  29.  
  30. /* Note the format specifier. %u was incorrect */
  31. fscanf(stdin, "%lu", &val);
  32.  
  33. if (val == testval)
  34. {
  35. return (func_t)foundit; /* Safe cast */
  36. }
  37. else
  38. {
  39. return (func_t)tryit; /* Safe cast */
  40. }
  41. }
  42.  
  43. int main()
  44. {
  45. func_t addr = (func_t)tryit; /* Safe cast */
  46.  
  47. fprintf(stdout, "ans->%u\n", 1U);
  48.  
  49. while (addr != null_func) {
  50. /* Cast back to the correct type before calling */
  51. addr = ((func_t(*)(void))addr)();
  52. }
  53.  
  54. /* A call to exit really isn't necessary from main */
  55. return 0;
  56. }
>But that isn't the problem...
>The problem is when I remove the comments from this line

It might actually be. In my experience, when commenting out random unrelated lines suddenly causes a broken program to work, it's often a result of undefined behavior.

>the code will not work correctly on GCC 4.4.1
>but it will work correctly on GCC 4.3.2, GCC 3.4.5

File a bug report and see what comes of it then.
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
Nov 8th, 2009
0
Re: Could Someone Try Compiling This On A Different Compiler
Click to Expand / Collapse  Quote originally posted by Narue ...
>No the complier had no problems casting a void pointer to a function..should it?
It might. Technically void* and functions pointers are incompatible and converting between them is undefined behavior.
Could you give an example....
Last edited by gerard4143; Nov 8th, 2009 at 11:05 am.
Reputation Points: 499
Solved Threads: 367
Postaholic
gerard4143 is online now Online
2,197 posts
since Jan 2008
Nov 8th, 2009
2
Re: Could Someone Try Compiling This On A Different Compiler
>Could you give an example....
Your code is an example, my fix for your code is a counter-example. What more do you want? How about a quote from the standard:
Quote originally posted by C99 Section 6.3.2.3 ...
1 A pointer to void may be converted to or from a pointer to any incomplete or object
type. A pointer to any incomplete or object type may be converted to a pointer to void
and back again; the result shall compare equal to the original pointer.
The key terms here are incomplete and object type. An object type is distinct from a function type, and incomplete types are defined as object types that lack size information.

I said "technically" in my original post because even the standard lists this as a common extension:
Quote originally posted by C99 Section J.5.7 ...
1 A pointer to an object or to void may be cast to a pointer to a function, allowing data to
be invoked as a function (6.5.4).
2 A pointer to a function may be cast to a pointer to an object or to void, allowing a
function to be inspected or modified (for example, by a debugger) (6.5.4).
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C Forum Timeline: Small C program error
Next Thread in C Forum Timeline: Need Help sorting structures





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC