Kipt Scriddy
Kipt Scriddy

Reputation: 763

How to make a pointer in a function change the pointee in C

Hee guys,

I have been reading a couple of things about pointers and pointees and started getting curious. The only thing I dont understand is how pointers behave in functions, hence the following code:

#include <stdio.h>

int pointeeChanger(char* writeLocation) {

    writeLocation = "something";
    return 0;
}

int main(void)
{

    char crypted[] = "nothing";
    char* cryptedPointer = crypted;

    pointeeChanger(cryptedPointer);

    printf("The new value is: %s", cryptedPointer);

    return 0;
}

What my intention to do is to adjust the pointee, "crypted" var, through a pointer given to a function. The only thing is that it is not working. Could you please explain me what is going wrong in my thought process. I am fairly new to C so my errors could be fairly basic.

Thanks in advance!

Greetings,

Kipt Scriddy

Upvotes: 1

Views: 192

Answers (4)

autistic
autistic

Reputation: 15642

Consider that Tom is hired by Sally to break knuckles for the mafia.

Pass-by-value: If Sally tells Tom to count the number of knuckles he breaks at work today, then Sally has no way of knowing which number Tom has come up with until he returns from the road. They both have a copy of the number "zero" in their heads to begin with, but Tom's number might increase throughout the course of the day.

Note the word "copy". When you pass-by-value to a function, you're passing a copy of the object. When you modify the object within a function, you're modifying the copy instead of the original.

Pass-by-reference: If Sally tells Tom to tally the number of knuckles he breaks in the sky, then she (and anyone else who's interested) can refer to the sky. By changing the sky, Tom would also be changing Sally's number.

edit: C doesn't have pass-by-reference, though it does have pointers, which are reference types. Passing a pointer is still pass-by-value, and a copy with the same pointer value is still formed. Hence, your assignment is to the copy, not the original.

Upvotes: 1

MatthewD
MatthewD

Reputation: 2534

Short answer: writeLocation is a local variable and is a copy of cryptedPointer. When you modify writeLocation, cryptedPointer is not modified.

If you want to modify cryptedPointer, you have to pass a pointer to it, like so:

#include <stdio.h>

int pointeeChanger(char** writeLocation) {            /* Note: char** */

    *writeLocation = "something";                     /* Note: *writeLocation */
    return 0;
}

int main(void)
{

    char crypted[] = "nothing";
    char* cryptedPointer = crypted;

    pointeeChanger(&cryptedPointer);                  /* Note: &cryptedPointer */

    printf("The new value is: %s", cryptedPointer);

    return 0;
}

There are other issues with this code though. After the call to pointeeChanger(), cryptedPointer no longer points to the crypted array. I suspect you actually wanted to change the contents of that array. This code fails to do that.

To change the value of crypted[] you will need to use strcpy() or (preferably) strncpy(). Also you will need to watch the size of the crypted[] array - "something" is longer than "nothing" and will cause a buffer overflow unless crypted[] is made larger.

This code will modify the original crypted[] array:

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

#define MAX_STR_LEN 64

/*
 * Only char* required because we are not modifying the
 * original pointer passed in - we are modifying what it
 * points to.
 */
int pointeeChanger(char* writeLocation)
{
    /*
     * In C, you need to use a function like strcpy or strncpy to overwrite a
     * string with another string. Prefer strncpy because it allows you to
     * specify a maximum size to copy, which helps to prevent buffer overruns.
     */
    strncpy(writeLocation, "something", MAX_STR_LEN);

    /* strncpy doesn't automatically add a \0 */
    writeLocation[MAX_STR_LEN] = '\0';

    return 0;
}


int main(void)
{
    /*
     * The +1 is because an extra character is required for the 
     * null terminator ('\0')
     */
    char crypted[MAX_STR_LEN + 1] = "nothing";

    pointeeChanger(crypted);

    printf("The new value is: %s", crypted);

    return 0;

}

Upvotes: 3

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726669

C strings are not the best material to learn pointers, because they are implemented as pointers to char. Let's use int instead:

#include <stdio.h>

void pointeeChanger(int* writeLocation) {
    // Using dereference operator "*"
    *writeLocation = 42; // something
}

int main(void) {
    int crypted = 0; // Nothing
    pointeeChanger(&cryptedPointer); // Taking an address with "&"
    printf("The new value is: %d", crypted);
    return 0;
}

This works as expected.

Modifying strings in place is a lot harder, because you are forced to deal with memory management issues. Specifically, the string into which you copy must have enough space allocated to fit the new string. This wouldn't work with "nothing" and "something", because the replacement is longer by two characters.

Upvotes: 4

Mats Petersson
Mats Petersson

Reputation: 129374

It depends slightly on what you actually want to do:

Do you want to change what cryptedPointer is pointing to, or change the content that cryptedPointer is pointing at?

The second can be done by:

  strcpy(writeLocation, "something"); 

Beware that if something is longer than what the original string's size, you'll overflow the buffer, which is a bad thing. So to fix this, you'd have to have char crypted[10] = "nothing";, to make space for the string "something".

You can clearly also do something like:

 writeLocation[2] = 'f';
 writeLocation[3] = 'f';

and have the printf print "noffing"

but if you want to do the first variant, then you need to pass a pointer to the pointer:

int pointeeChanger(char** writeLocation) {

    *writeLocation = "something";
    return 0;
}

And then call:

pointeeChanger(&cryptedPointer); 

Note that when this returns, cruptedPointer is pointing at a constant string that can't be modified, where your original crypted can be modified.

Upvotes: 2

Related Questions