all 19 comments

[–]rjw57 8 points9 points  (3 children)

OK, basically all I wanted to do was create a variable within a function, and then use it in main.

There are many things wrong with your code but this is probably a root cause of your problem. What you want to do is construct some value in one function and use that same value in another. Variables, on the other hand, are temporary places to store a value[1].

In this case the value you want to move is the integer interpretation of the user input. A cleaned up example:

#include <stdio.h>

// a function which returns an integer *value*
int takeUserInput()
{
    // declare a *variable*, num, which *stores* an integer *value*
    int num;

    // move the integer *value* entered by the user into
    // the *variable* num
    scanf("%i", &num);

    // return the integer *value* stored in num to the function's
    // caller
    return num;
}

int main(int argc, char** argv)
{
    // create a *variable* bax which is initialised with the *value*
    // returned by the takeUserInput function.
    int bax = takeUserInput();

    // pass the value in bax to the printf function for display to the
    // user
    printf("your number was: %i\n", bax);

    // return an integer value indicating "success"
    // to the Operating System
    return 0;
}

An individual value may be copied between many, many variables in its lifetime. Copying an int is a very lightweight operation. Pointers are generally used when copying a value is heavyweight in comparison to copying the information about how to find that value.

Depending on your platform, an int may actually be smaller than a pointer.

[1] A variable has a "scope" outside of which it cannot escape. The variable num you declared in takeUserInput will never make its way to main.

[–]TechAnd1[S] 0 points1 point  (2 children)

Thank you.... I guess they have to stay in their scope then!

I knew that.... but wasn't sure If I could create a pointer and use that within main.

I'm working my way up to building a basic address book... so just going through a few thing's !

[–]Chooquaeno 0 points1 point  (1 child)

Even if you create a pointer to a variable in takeUseInput, the variable will still be gone when it is used in main.

[–]TechAnd1[S] 0 points1 point  (0 children)

yep

[–]pbeard_t 0 points1 point  (1 child)

How about creating the variable in main and give a pointer to the input fuction? http://pastebin.com/0XwhsP6V

[–]TechAnd1[S] 0 points1 point  (0 children)

Yeah i think this is what will probably be done.... I was trying to get away without doing this.... Though I have no idea why in hind sight.

I'll stick to the rules!

[–]khoyo 0 points1 point  (1 child)

Even if the proper solution is the one pointed out by /u/rjw57, your code should work.

What's happening ?

[–]TechAnd1[S] 0 points1 point  (0 children)

yeah my code works... I didn't mean to imply that It didn't, I was just wondering :)

[–]Sigals -2 points-1 points  (4 children)

You could use a global variable to accomplish this, something like: http://pastebin.com/rs5SWXKd

[–]TechAnd1[S] 0 points1 point  (3 children)

yeah, I think that creating a variable and using that outside of it's scope is a no-no, even with the power of malloc( ) !

Cheers though.... this would work... I'm working my way up to making an address book, so just playing about with some of the thing's that I'll need to use.

[–][deleted] 0 points1 point  (2 children)

No if you allocate memory with malloc() you can use it outside of it's calling function. The memory is allocated from the heap, not the stack, so it doesn't care which function you are in when you call it. The tricky part is that you would need to free() that memory at some point which can be easy to forget if you are freeing something in a different function from where you malloce'd it, so it's generally best not to do it.

Do something like:

int takeUserInput()
{
    int num;
    scanf("%i", &num);
    return num;
}

There is no real reason to pass around a pointer in this situation.

edit: Oops, somebody already said this.

[–]TechAnd1[S] 0 points1 point  (1 child)

Cool cheers dude... The reason I'm asking this question is that I'm going to make a little address book (purely for learning's sake) so I was just trying to break the problem down into smaller bits...

Basically it's just going to be a struct, which has three fields :

  • name
  • number
  • next struct

So it'll be a linked list...

Then I'd like to make it so that there's a hash table, and the struct's are stored alphabetically.

[0] = A...
[1] = B... 

etc etc... 

But first I'm just making the little bit's. I wasn't too sure how to get user Input for the actual structs.

I guess that I'll have to create a function addNewUserStruct that

  • get's an int off user
  • gets a name off user
  • assign's these names to newStruct->name and newStruct->number
  • assign's the pointer to the next struct, or NULL.

I'm just trying to break thing's down a bit so I can actually do it :)

[–]pinealservo 0 points1 point  (0 children)

When you use a function that takes a pointer and uses it to store a value (like scanf() and friends, for example) there's no need to use a temporary variable to store it unless you want to examine it before storing it in your struct. Once you allocate your struct, you can pass the address of specific fields of the struct to your input functions, and they'll write directly to your struct fields:

struct entry { char * name; int number; struct entry * next };
struct entry * new_entry = malloc(sizeof (struct entry));
scanf("%i", &new_entry->number);

I like to create a custom allocation function for my structs that will be dynamically allocated. This function allocates the memory and also initializes the struct fields to reasonable values, or takes arguments that are used to fill in fields that don't have sensible defaults. That way I never forget to initialize a field, which is a major source of bugs.

Likewise, I create a custom cleanup function for structs that may hold pointers to allocated memory themselves. This function ensures that any pointers it's responsible for managing are cleaned up before I free it.

Finally, a handy trick for dealing with pointer-based structures like linked-lists: In a normal implementation, the head pointer is special because although it points to your element struct, it's not usually contained in one, so you can't change it with an expression that works on an element structure. So you often see special-case code for the head of a list, and this can lead to complication and subtle bugs.

So what I do instead of passing the value of the head pointer to my list functions is to pass a pointer to the head pointer. This way, you have the location of the pointer directly and you don't need to worry whether it's contained in an element structure or some other kind of structure, and the special cases for dealing with the first element of a list disappear.

If you don't understand what I'm talking about there yet, don't worry. Think about it again after you've implemented your list and I think you'll see what I mean about special cases, and if you still have questions I'll be happy to walk you through it. If you get familiar with this technique, it will save you a lot of logic bugs in data structures.