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

    Join Date
    Jan 2013
    Posts
    14
    Rep Power
    0

    Pointer to a char trouble with scanf


    I have never tried this but could something like this work? The following way I want to scanf a char * Is there a way around?

    I would also like to know in a quickie
    1.Pointer to a function in action, if anyone can explain it clearly with a very short example.
    2. How pointer to a multidimensional array can be utilized,accessed?
    thanks

    Code:
    int main()
    {
        char *name;
        int len=0;
        puts("Enter a string");
        scanf("%s",&name);
        printf("\n string is %s",name);
    }
    O/P:
    Enter a string
    build

    Process returned -1073741819 (0xC0000005) execution time : 4.625 s
    Press any key to continue.
    I searched, there was a question like this here:
    http://www.daniweb.com/software-development/c/threads/329405/scan-a-string-to-char-name-inside-struct-data

    but it still doesn't ans the question of whether we can scan straight from the *charname??
    Last edited by lovecodecakes; February 6th, 2013 at 01:23 PM. Reason: added additional links
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Code:
    int main()
    {
        char *name;
        int len=0;
        puts("Enter a string");
        scanf("%s",&name);
        printf("\n string is %s",name);
    }
    Two problems with that:
    1. scanf("%s",&name); -- "%s" expects a char pointer, but name is already a char pointer, so you would not use that ampersand address operator, but rather just the char pointer variable, name.
    What you are instead doing is that you are giving scanf the address of the pointer variable and telling it to store that string there. That would over-write name (AKA "clobber") with that string. If the string is (sizeof(char*) -1) or fewer characters long, then that is all that you would be damaging, but if it's longer then you will also be clobbering the memory that comes after name; eg, the int variable, len, if that's the side of name where it's stored, function control values such as the return value, arguments, stack frame location. Such clobbering will either corrupt other variables or cause the program to crash; since the process had returned a non-zero value, it looks like it crashed.

    2. char *name; -- assuming that you had done the scanf correctly, there's still the problem that name is uninitialized and you would be attempting to use it before having initialized it. Where is name pointing? It does contain an address, a garbage value that just happens to have been left in that memory location after something else had used it and that is now being interpreted as a memory address where you can store that input string. But where? It's almost guaranteed to be pointing to a memory location that's already being used not only for something else, but also by some other process in which case your program will be terminated by the OS.

    Before you can use a char pointer in a scanf, you need to initialize it to point to memory where it's safe to store that input string. Actually, the same applies to any function or code that's going to store a string to where the pointer is pointing. So you can assign the pointer to or into an existing char array, or you can malloc or calloc some memory and assign that address to the char pointer. But the char pointer must be initialized and it must be pointing to memory specifically designated for receiving that string.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    14
    Rep Power
    0
    @dwise assuming you mentioned, initialize it & I take that like array[] needs no "&" while scanf, char* variable name here to doesn't need either, but instead of initializing it to a char array, what I wanted was to have an array the size of what the user feeds not a pre-defined char array, the whole purpose would be defeated.

    Do you mean char *name=malloc(sizeof(name))?? something like that? well not name, that's 1byte only.but something like a bigger datatype?

    Is it possible at all to not use char array[] & just have a definite user defined I/p given string stored there through scanf()? Im guessing the moment user "enters", it's \n & not \0 while to not eat other memory usage of other programs upon OS, char *name needs a \0. Am I right?
    Is there a way around?

    Originally Posted by dwise1_aol
    Code:
    int main()
    {
        char *name;
        int len=0;
        puts("Enter a string");
        scanf("%s",&name);
        printf("\n string is %s",name);
    }
    Two problems with that:
    1. scanf("%s",&name); -- "%s" expects a char pointer, but name is already a char pointer, so you would not use that ampersand address operator, but rather just the char pointer variable, name.
    What you are instead doing is that you are giving scanf the address of the pointer variable and telling it to store that string there. That would over-write name (AKA "clobber") with that string. If the string is (sizeof(char*) -1) or fewer characters long, then that is all that you would be damaging, but if it's longer then you will also be clobbering the memory that comes after name; eg, the int variable, len, if that's the side of name where it's stored, function control values such as the return value, arguments, stack frame location. Such clobbering will either corrupt other variables or cause the program to crash; since the process had returned a non-zero value, it looks like it crashed.

    2. char *name; -- assuming that you had done the scanf correctly, there's still the problem that name is uninitialized and you would be attempting to use it before having initialized it. Where is name pointing? It does contain an address, a garbage value that just happens to have been left in that memory location after something else had used it and that is now being interpreted as a memory address where you can store that input string. But where? It's almost guaranteed to be pointing to a memory location that's already being used not only for something else, but also by some other process in which case your program will be terminated by the OS.

    Before you can use a char pointer in a scanf, you need to initialize it to point to memory where it's safe to store that input string. Actually, the same applies to any function or code that's going to store a string to where the pointer is pointing. So you can assign the pointer to or into an existing char array, or you can malloc or calloc some memory and assign that address to the char pointer. But the char pointer must be initialized and it must be pointing to memory specifically designated for receiving that string.
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Let's start of with some basic facts to keep in mind so that we can then apply them to the answers.

    1. When you store a string (or anything else for that matter), it needs to go somewhere. There will be actual memory locations that will get filled. Those memory locations have to be allocated for that use. And the memory allocated needs to be of sufficient size. For built-in data types (eg, int, float, char), declaring a variable of that type satisfies those requirements.

    For a C-style string, you can either declare a char array or malloc/calloc memory space from the heap. In either case, you must allocate enough space for the longest-possible string that it will hold plus one more char for the null-terminator.

    DEFINITIONS:
    static vs dynamic -- when you create a char array at compile time with an array declaration, then that is static because it's created before the program starts to run and cannot be changed until the program ends. When you malloc or calloc or realloc that char array during run-time, then that is creating it dynamically.

    2. scanf needs memory addresses to know where to store the values it inputs. For variables of built-in types, you need to use the & address operator to convert the variable name (which represents the value that it contains) to the address of that variable. Since pointers and array names are already memory addresses, you do not use the & address operator on them.

    Hopefully, keeping those two basic principles in mind will shorten my answers.

    Originally Posted by lovecodecakes
    @dwise assuming you mentioned, initialize it & I take that like array[] needs no "&" while scanf, char* variable name here to doesn't need either, but instead of initializing it to a char array, what I wanted was to have an array the size of what the user feeds not a pre-defined char array, the whole purpose would be defeated.
    Yes, you can indeed do that. The entire purpose of dynamic allocation (ie, via malloc or calloc) is to handle data structures the size and number of which you cannot know until run-time. Otherwise, to do that statically you would need to create all arrays, etc, to be of some arbitrary maximum size that would eat up lots of resources -- in the olden days when this capability was created, memory, disk space, and processing power were small and scarce, so conserving those scarce resources was very desirable.

    Dynamic memory allocation works best when you know how much to allocate. When copying strings into a struct, strlen+1 tells you how much to allocate. When an input file tells you how many items it has for you to read in and store in an array, you know how big to make that array.

    The problem with keyboard input strings is that you do not know ahead of time how big to make that dynamically allocate string. So while you can still malloc that string instead of declaring a state char array, you will still need to make it an arbitrarily large-enough size and you will still need to guard against the user inputting more than you had allocated for -- that is the basis of buffer-overflow problems and attacks. For example, if you use gets to input one line of input, you have no way to guard against buffer-overflow. For that reason, fgets(stdin, .. , ..) is recommended instead. In the case of scanf, I don't know whether there's any way to limit the amount of input -- I work mainly in embedded programming and so don't work with scanf much.

    So then, yes, you can create the input buffer dynamically, but you won't know yet how big to make it.

    Originally Posted by lovecodecakes
    Do you mean char *name=malloc(sizeof(name))?? something like that? well not name, that's 1byte only.but something like a bigger datatype?
    Yes, though it would be more like:
    char *name=malloc(sizeof(char) * (MAX_CHARS + 1);
    where MAX_CHARS would be the maximum number of characters that the buffer can hold. And, again, how you arrive at that number is the problem.

    Originally Posted by lovecodecakes
    Is it possible at all to not use char array[] & just have a definite user defined I/p given string stored there through scanf()?
    Yes, but in keeping with the preceeding concerns.

    Originally Posted by lovecodecakes
    Im guessing the moment user "enters", it's \n & not \0 while to not eat other memory usage of other programs upon OS, char *name needs a \0.
    There is no way around the null-terminator, '\0'; you must always allocate room for it. If you read in the newline ('\n'), then you will also need to make room for it. For example, gets stores the entire input line without the newline, whereas with fgets(stdin) you also get the newline at the end of the string (along with the null-terminator, of course). I don't really know about scanf, though that would undoubtedly depend on the format string.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally Posted by lovecodecakes
    1.Pointer to a function in action, if anyone can explain it clearly with a very short example.
    As for function pointers, I'm not sure what you've asking for specifically.

    We pre-define our function pointer types with typedef declarations, such as:
    Code:
    typedef void (*APF)(unsigned char *);   // ptr to funct with pointer parameter
    typedef void (far *PF)(void);               // ptr to funct
    typedef void (*cmdPF)(int,char *);      // ptr to funct with (int,*char)
    As you can see, each possible combination of return type and parameter list will result in a different type of function pointer, much like the difference between an int pointer and a float pointer. IOW, the type of pointer that it is determines how the compiler will use it.

    {ABE: This matter of the type of pointer determining how the compiler will treat it is more important that may appear. For example, how you interpret a dereferenced pointer depends on what type it points to. When you increment a pointer, the number of bytes that gets added to that address depends on the sizeof of the pointer's datatype. But it's even more important with function pointers because in order to prepare a call to a function, the compiler has to insert a lot of code to prepare for that call (which is a simple jump while saving the return address), including code to process that function's arguments (eg, how many, what type, how to evaluate the argument, where to store it on the stack so that the function's code knows where to find it); that kind of set-up code is called thunk code, as I was taught. Because of all that, different function pointers (ie, having different return types or different argument list item number and types) are very incompatible with each other. }

    In the three examples, the type names are APF, PF, and cmdPF. Then when you use a function name, it's interpreted as a pointer to that function, the memory address that that function starts at. For example, we have several tens of commands that are processed by functions that are declared the same way as cmdPF. So we declared a struct of two fields: a char array of the command name and a cmdPF that points to the function that processes that command. And we construct an array of that struct and into each entry we pair up a command name with the name of the function that we will call to process that command -- that kind of an array is called a jump table. Then when we receive a command, we search for its entry in the jump table and we call its function thus:
    (*CmdTbl[i].CmdFunct)(port,Cmd);
    CmdTbl is the jump table, CmdTbl[i].CmdFunct is the function pointer in the i'th entry in that table, and with that asterix we're dereferencing the pointer with the argument list following it.

    If you can, get hold of a copy of Schaum Outlines' Programming in C by Byron Gottfried. Chapter 10 is on pointers. At the end of that chapter, pages 323 and 324, there's a list of 20 different kinds of pointer declarations. That alone is worth the price of the book ($16.95 US), though the rest of the book is also a very good reference.

    There's also a classic book entirely about C pointers. And somebody's signature on this forum has a link to an on-line resource that's "all about pointers", as I recall. You could even use Google to find examples.
    Last edited by dwise1_aol; February 7th, 2013 at 01:16 AM.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    14
    Rep Power
    0
    @dwise. That helps a lot in the basics of pointers. Yea Im starting out in embedded only myself.

    Originally Posted by dwise1_aol
    As for function pointers, I'm not sure what you've asking for specifically.

    We pre-define our function pointer types with typedef declarations, such as:
    Code:
    typedef void (*APF)(unsigned char *);   // ptr to funct with pointer parameter
    typedef void (far *PF)(void);               // ptr to funct
    typedef void (*cmdPF)(int,char *);      // ptr to funct with (int,*char)
    As you can see, each possible combination of return type and parameter list will result in a different type of function pointer, much like the difference between an int pointer and a float pointer. IOW, the type of pointer that it is determines how the compiler will use it.

    {ABE: This matter of the type of pointer determining how the compiler will treat it is more important that may appear. For example, how you interpret a dereferenced pointer depends on what type it points to. When you increment a pointer, the number of bytes that gets added to that address depends on the sizeof of the pointer's datatype. But it's even more important with function pointers because in order to prepare a call to a function, the compiler has to insert a lot of code to prepare for that call (which is a simple jump while saving the return address), including code to process that function's arguments (eg, how many, what type, how to evaluate the argument, where to store it on the stack so that the function's code knows where to find it); that kind of set-up code is called thunk code, as I was taught. Because of all that, different function pointers (ie, having different return types or different argument list item number and types) are very incompatible with each other. }

    In the three examples, the type names are APF, PF, and cmdPF. Then when you use a function name, it's interpreted as a pointer to that function, the memory address that that function starts at. For example, we have several tens of commands that are processed by functions that are declared the same way as cmdPF. So we declared a struct of two fields: a char array of the command name and a cmdPF that points to the function that processes that command. And we construct an array of that struct and into each entry we pair up a command name with the name of the function that we will call to process that command -- that kind of an array is called a jump table. Then when we receive a command, we search for its entry in the jump table and we call its function thus:
    (*CmdTbl[i].CmdFunct)(port,Cmd);
    CmdTbl is the jump table, CmdTbl[i].CmdFunct is the function pointer in the i'th entry in that table, and with that asterix we're dereferencing the pointer with the argument list following it.

    If you can, get hold of a copy of Schaum Outlines' Programming in C by Byron Gottfried. Chapter 10 is on pointers. At the end of that chapter, pages 323 and 324, there's a list of 20 different kinds of pointer declarations. That alone is worth the price of the book ($16.95 US), though the rest of the book is also a very good reference.

    There's also a classic book entirely about C pointers. And somebody's signature on this forum has a link to an on-line resource that's "all about pointers", as I recall. You could even use Google to find examples.
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    A professional trying to come up to speed in C?

    Definitely look into that Schaum Outlines book.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    14
    Rep Power
    0
    Yes sir something like that.
    I appreciate all your help. I'll get that book on C by Byron Gottfried.
    Originally Posted by dwise1_aol
    A professional trying to come up to speed in C?

    Definitely look into that Schaum Outlines book.

IMN logo majestic logo threadwatch logo seochat tools logo