#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2

    Generic way to obtain input


    i'm trying to find a generic way to obtain input according to user preference.
    this is what i've tried:

    Code:
    typedef void* (*input_t)();
    
    void* InputStr()
    {
    	void* voidPtr;
    	char buffer[50];
    	scanf("%s", buffer);
    	voidPtr=buffer;
    	return voidPtr;
    }
    
    void* InputInt()
    {
    	void* voidPtr;
    	int inputNum;
    	scanf("%d", &inputNum);
    	voidPtr=&inputNum;
    	return voidPtr;
    }
    
    int main()
    {
    	char choice;
    	input_t Input;
    	...
    	...
    	printf("1. int\n");
    	printf("2. strings\n");
    	scanf(" %c", &choice);
    
    	if (choice=='1') Input=InputInt(); //i'm getting a warning here
    	if (choice=='2') Input=InputStr(); //and here
    	...
    	...
    	...
    }
    the warning is: "assignment makes pointer from integer without a cast[enabled by default]"

    i couldn't figure out what's wrong there.

    thanks in advanced!
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,175
    Rep Power
    2222
    Instead, try:
    Code:
    	if (choice=='1') Input=InputInt; //i'm getting a warning here
    	if (choice=='2') Input=InputStr; //and here
    InputInt() is a call to that function, so its type is the return type, void*.
    InputInt is a pointer to that function, so its type is input_t.
  4. #3
  5. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,392
    Rep Power
    1871
    > void* InputStr()
    > void* InputInt()
    Both of these are returning pointers to local variables.

    When the function exits, the variables go out of scope, and as a result, any pointer is now pointing at garbage.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Thanks for the help.

    Originally Posted by dwise1_aol
    Instead, try:
    Code:
    	if (choice=='1') Input=InputInt; //i'm getting a warning here
    	if (choice=='2') Input=InputStr; //and here
    InputInt() is a call to that function, so its type is the return type, void*.
    InputInt is a pointer to that function, so its type is input_t.
    that gives me a compilation error.

    **edit
    my bad.
    it works perfectly fine.
    i forgot to declare the functions... :cool:

    Originally Posted by salem
    > void* InputStr()
    > void* InputInt()
    Both of these are returning pointers to local variables.

    When the function exits, the variables go out of scope, and as a result, any pointer is now pointing at garbage.
    OK,
    do you have any other ideas for me? :tbulb:
    is there a way to return a pointer properly?
    Last edited by so.very.tired; February 18th, 2013 at 03:56 PM.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,175
    Rep Power
    2222
    Those local variables you return pointers to, declare them as static. This will make them stored in static memory along with the global variables and hence they will continue to exist after returning from the function.

    One side-effect to watch out for is that if you call the function again before having saved the value then the second call will overwrite the value of the first.
    Last edited by dwise1_aol; February 18th, 2013 at 04:13 PM.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi dwise1_aol, and thanks for the help.

    Oddly enough, the following code segments seems to work:

    Code:
    void* InputInt()
    {
    	void* voidPtr;
    	int inputNum;
    	scanf("%d", &inputNum);
    	voidPtr=&inputNum;
    	return voidPtr;
    }
    
    
    int main()
    {
    	int *ptr;
    	printf("Enter a number: ");
    	ptr=InputInt();
    	printf("%d", *ptr);
    }
    ------------------------------------------------

    Code:
    void* InputInt()
    {
    	int inputNum;
    	scanf("%d", &inputNum);
    	return &inputNum;
    }
    
    
    int main()
    {
    	int *ptr;
    	printf("Enter a number: ");
    	ptr=InputInt();
    	printf("%d", *ptr);
    }
    the output is correct...
    i don't understand how can it be? in both cases the variable inputNum is local and is not static.
    why does it work?

    Although, in the second code segment the compiler at least has the decency to warn me... ("function returns address of local variable")
  12. #7
  13. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,392
    Rep Power
    1871
    > why does it work?
    Pure dumb luck.

    It only 'works' because you almost immediately dereference the pointer before the stack space is re-used for something else.
    Code:
    #include <stdio.h>
    void* InputInt()
    {
      int inputNum;
      scanf("%d", &inputNum);
      return &inputNum;
    }
    
    void trash( void ) {
      int var = 99999;  //!! high probability that this has the same address as inputNum above
      printf("Stack Space reused as %d\n", var );
    }
    
    int main()
    {
      int *ptr;
      printf("Enter a number: ");
      ptr=InputInt();
      trash();
      printf("%d\n", *ptr);
    }
    
    
    $ gcc -Wall foo.c
    foo.c: In function ‘InputInt’:
    foo.c:6:3: warning: function returns address of local variable [enabled by default]
    foo.c: In function ‘main’:
    foo.c:21:1: warning: control reaches end of non-void function [-Wreturn-type]
    $ 
    $ ./a.out 
    Enter a number: 12345
    Stack Space reused as 99999
    99999
    If anything else happens (even an interrupt from the OS which you have no control over), then your chances of success diminish rapidly.

    It's one thing to be wary of. All sorts of bad code 'works' in very small test environments, only to fail when it gets put into something much larger.

    Small broken code is broken, but small 'working' code is not an immediate guarantee in a generalised case. You really do need to know the rules (semantics - what it all means). You can't just rely on "well it compiles".

    Ancient compilers were famous (or infamous) for compiling anything that wasn't an outright syntax error. Modern compilers have lots of warning (so enable them all, and pay attention), such as "returning address of local". Compiler writers don't put these in just because it's an interesting observation, it's because such code is wrong on a semantic level.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    OK, i found a workaround. :o
    Code:
    void Input(void** key)
    {
    	*key=malloc(sizeof(int));
    	scanf("%d", (int*)(*key));
    }
    
    
    int main()
    {
    	void *ptr;
    	printf("Enter a number: ");
    	Input(&ptr);
    	printf("%d", *(int*)ptr);
    }

    thank you all!
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi salem! :)

    thanks for the great explanation.
  18. #10
  19. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,392
    Rep Power
    1871
    > OK, i found a workaround.
    That would work - but you also need to call free() when you're done with the input.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Originally Posted by salem
    > OK, i found a workaround.
    That would work - but you also need to call free() when you're done with the input.
    yup, i know.
    the above code is a small piece from the whole program... :)

IMN logo majestic logo threadwatch logo seochat tools logo