简体   繁体   中英

Increasing Value of String Pointer in C

I am working on an assignment. I have the proper working code, however, I am having trouble understanding what one line does.

The description for a function is:

This function will malloc 5 bytes of memory, store "bird" in those 5 bytes (4 letters plus '\\0') using strcpy, and increase the value pointed to by the string pointer by the length of the string (calculated using strlen) that it points to (so it ends up pointing to the '\\0' at the end of the sentence). Then it will return the malloced memory.

Here is the code to do what is described above

char *get_word( char **string_ptr ){

    char *word; 

    word = malloc( 5 ); 

    strcpy( word, "bird" ); 

    *string_ptr += strlen( *string_ptr );

    return word;

}

I do not understand what the line "*string_ptr += strlen( *string_ptr );" does, even with the description above. Could someone give me a more detailed explanation of what happening there?

The parameter passed to get_word is char ** (presumably due to the caller passing the address of the string rather than a collection of pointers).

Since all parameters in C are passed-by-value, in order to change the address of a pointer passed as a parameter, you must pass the address of the pointer. Otherwise, the function will simply receive a copy of the pointer (with its very own and very different address) and any changes made to the pointer within the function will not be visible back in the calling function.

While you have not provided a A Minimal, Complete, and Verifiable Example (MCVE) , we can deduce from your function that the address of a string is being passed to get_word , something like:

#define MAXC 1024
...
char buffer[MAXC] = "word_one";
char *p = buffer;
char *new_word = NULL;
...
new_word = get_word (&p);

Then later there is something done to append text at the end of that pointer (which was the purpose for *string_ptr += strlen( *string_ptr ); in get_word ), something like:

strcpy (p, new_word);

The result being, buffer would now contain:

"word_onebird"

So in effect, by passing the address of a pointer to get_word , the pointer is advanced to the end of the current word in string_ptr by *string_ptr += strlen( *string_ptr ); and the change to where string_ptr is pointing is reflected back in the calling function.

Had you only passed get_word(string_ptr) , the change made in get_word would not be visible back in the calling function, and the pointer there would be unchanged. But, by passing the address of string_ptr with get_word(&string_ptr) , the change in get_word (which operates on the original pointer itself through *string_ptr = ... is reflected in the original pointer back in the calling function.


Understanding Pointers By Example

A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int a = 5; , a pointer would simply hold the address where 5 is stored in memory, eg int *b = &a; . It works the same way reqardless what type of object the pointer points to. (a pointer, is just a pointer....)

If you need to change the address pointed to by a pointer within a function without returning the new pointer, you must pass the address of the original pointer as a parameter so that the function can operate on the original pointer itself, rather than a copy of the pointer which would be present in the function if the parameter took the pointer itself.

An example may help. Take time to work through the code and understand how the original pointer is available in get_word , but only a copy of the original is available in get_word_single below:

#include <stdio.h>
#include <string.h>

#define MAXC 256

/* parameter passes only the pointer p in main() */
void get_word_single (char *string_ptr)
{
    printf ("in get_word_single()\n"
            " address of string_ptr: %p  <-- a new pointer\n"
            "   value in string_ptr: %p  <-- changes only seen locally\n\n",
            (void*)&string_ptr, (void*)string_ptr);

    string_ptr += strlen (string_ptr);
}

/* parameter passes address of p in main() */
void get_word (char **string_ptr)
{
    printf ("in get_word()\n"
            "address of  string_ptr: %p  <-- a new pointer\n"
            "  value in  string_ptr: %p  <-- holding original address\n\n"
            "address of *string_ptr: %p  <-- dereference to expose address\n"
            "  value in *string_ptr: %p  <-- modify to change original\n\n",
            (void*)&string_ptr, (void*)string_ptr, 
            (void*)&(*string_ptr), (void*)*string_ptr);

    *string_ptr += strlen (*string_ptr);
}

int main (void) {

    char buf[MAXC] = "one",     /* a 3-character word in buf */
        *p = buf;

    printf ("in main()\n"
            "address of p: %p  <-- address of the pointer itself\n"
            "  value in p: %p  <-- address held by the pointer\n\n", 
            (void*)&p, (void*)p);

    get_word_single (p);

    printf ("in main()\n"
            "address of p: %p  <-- address of pointer itself unchanged\n"
            "  value in p: %p  <-- no change in address held\n\n", 
            (void*)&p, (void*)p);

    get_word (&p);

    printf ("in main()\n"
            "address of p: %p  <-- address of pointer itself unchanged\n"
            "  value in p: %p  <-- address held incremented by 3\n\n", 
            (void*)&p, (void*)p);

    return 0;
}

Example Use/Output

$ ./bin/passaddrex
in main()
address of p: 0x7ffc8594f370  <-- address of the pointer itself
  value in p: 0x7ffc8594f380  <-- address held by the pointer

in get_word_single()
 address of string_ptr: 0x7ffc8594f378  <-- a new pointer
   value in string_ptr: 0x7ffc8594f380  <-- changes only seen locally

in main()
address of p: 0x7ffc8594f370  <-- address of pointer itself unchanged
  value in p: 0x7ffc8594f380  <-- no change in address held

in get_word()
address of  string_ptr: 0x7ffc8594f348  <-- a new pointer
  value in  string_ptr: 0x7ffc8594f370  <-- holding original address

address of *string_ptr: 0x7ffc8594f370  <-- dereference to expose address
  value in *string_ptr: 0x7ffc8594f380  <-- modify to change original

in main()
address of p: 0x7ffc8594f370  <-- address of pointer itself unchanged
  value in p: 0x7ffc8594f383  <-- address held incremented by 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM