Silver Sky
Silver Sky

Reputation: 427

C - How to increment a pointer to a string through a function?

I want to execute the following code, but through a function.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(){
    char* string = "hello_World";
    string++;
    printf("%s\n", string);
    // ignore memory leak for sake of quiz
    return 0;
    }

OUTPUT:

ello_World

Now instead of incrementing the pointer inside main I tried to pass the reference of the pointer to a function and then increment it.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    void myfunc(char** param){
    param++;
    }

    int main(){
    char* string = "hello_World";
    myfunc(&string);
    printf("%s\n", string);
    return 0;
    }

But the OUTPUT was hello_World

Can you please tell me what is happening in the code that I wrote and how can I change it for the desired result?

Upvotes: 2

Views: 793

Answers (3)

H.S.
H.S.

Reputation: 12669

In myfunc() function, the pointer param is pointing to string pointer. It will look something like this:

        ---
  param |-|--
        --- |
            |
            |
           ---
   string  |-|----
           ---   |
                 |
                 |
                 --------------------------
                 |h|e|l|l|o|_|W|o|r|l|d|\0|
                 --------------------------

When you do param++, it will result in incrementing the pointer by the size of pointer1) on your platform because param can point to a char pointer. Assume that size of pointer is 8 (64 bit platform) and assume the address of string pointer is 100, then param++ will result in pointer param pointing to 108 address. Note that it will not affect string pointer in anyway. It will look something like this:

                             108
                   ---       ---
param++ -->  param |-|-------| |
                   ---       ---
            
           
           ---
   string  |-|----
           ---   |
                 |
                 |
                 --------------------------
                 |h|e|l|l|o|_|W|o|r|l|d|\0|
                 --------------------------

Now, when you print the string in main() function, you are getting the output "hello_World".

To demonstrate this, I have added few printf() statement in your program:

#include <stdio.h>

void myfunc(char** param){
    printf ("param : %p\n", (void *)param);
    printf ("*param : %p\n", (void *)*param);
    param++;
    printf ("param : %p\n", (void *)param);
    printf ("*param : %p\n", (void *)*param);
}

int main(void){
    char* string = "hello_World";
    printf ("string : %p\n", (void *)string);
    myfunc(&string);
    printf ("string : %p\n", (void *)string);
    printf("%s\n", string);
    return 0;
}

Output:

string : 0x10a654f97
param : 0x7ffee55abad0
*param : 0x10a654f97
param : 0x7ffee55abad8  ======> result of incrementing param
*param : 0xcb7d025      ======> result of incrementing param
string : 0x10a654f97    ======> not affected
hello_World

To get the desired behaviour, in the myfunc() function, you should first dereference the param pointer to get the string pointer and then increment it i.e. you should do (*param)++. It will result in increment the string pointer by size of a char1):

                       ---
                 param |-|--
                       --- |
                           |
                           |
                          ---
(*param)++  -->   string  |-|-------
                          ---      |
                                   |
                                   |
                                --------------------------
                                |h|e|l|l|o|_|W|o|r|l|d|\0|
                                --------------------------

Demonstration:

#include <stdio.h>

void myfunc(char** param){
    printf ("param : %p\n", (void *)param);
    printf ("*param : %p\n", (void *)*param);
    (*param)++;
    printf ("param : %p\n", (void *)param);
    printf ("*param : %p\n", (void *)*param);
}

int main(){
    char* string = "hello_World";
    printf ("string : %p\n", (void *)string);
    myfunc(&string);
    printf ("string : %p\n", (void *)string);
    printf("%s\n", string);
    return 0;
}

Output:

string : 0x100de5f97
param : 0x7ffeeee1aad0
*param : 0x100de5f97
param : 0x7ffeeee1aad0
*param : 0x100de5f98
string : 0x100de5f98
ello_World

  1. When increment a pointer, it gets incremented in steps of the object size that the pointer can point to.

Upvotes: 3

KamilCuk
KamilCuk

Reputation: 140970

The memory could be looking like the following. The 0x1122***** represent some address of the byte below it. Each +---+ box represents one byte with the value inside. Below are the function names with variable names. The ----> arrows represent "points to" relation between pointer and memory. The illustration assumes a pointer has 4 bytes and data are stored in big endian, which is most probably not true on the architecture you are running, but it's just to illustrate the point.

0x11223000                                       0x11223300                              0x11223344
+------+------+------+------+                    +------+------+------+------+           +---+---+---+---+---+---+---+---+---+---+---+------+
| 0x11 | 0x22 | 0x33 | 0x00 | . . . . . . . . .  | 0x11 | 0x22 | 0x33 | 0x44 | . . . . . | h | e | l | l | e | _ | W | o | r | l | d | 0x00 |
+------+------+------+------+         +--------->+------+------+------+------+           +---+---+---+---+---+---+---+---+---+---+---+------+
                                      |                                                  ^
+---------------------------+---------+          +---------------------------+-----------+
       myfunc::param                                     main::string

When you do param++ in myfunc you are incrementing the value of param, not the value it points to. Pointers are increment by the size they are pointing to, so param beeing char** will be incremented by sizeof(char*). In my illustration above, a pointer has 4 bytes, so doing param++ increments param = 0x11223300 to param = 0x11223304 and it points somewhere after main::string into some unknown memory region.

If you mean to do this:

0x11223300                              0x11223344
+------+------+------+------+           +---+---+---+---+---+---+---+---+---+---+---+------+
| 0x11 | 0x22 | 0x33 | 0x45 | . . . . . | h | e | l | l | e | _ | W | o | r | l | d | 0x00 |
+------+------+------+------+           +---+---+---+---+---+---+---+---+---+---+---+------+
                                            ^
+---------------------------+---------------+
        main::string

Then you have to increment the string pointer inside main. Because param points to string, you may (*param)++ - increment the value of what the param points to, so increment the string pointer inside main. Because string is a char*, it will be incremented by sizeof(char) - which is 1.

Upvotes: 3

Colin
Colin

Reputation: 3524

You incremented the pointer to the pointer, you would need (*param)++;

Upvotes: 3

Related Questions