0

I'm playing with pointers and array and I found it hard to understand why this code doesn't work.

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

void change(char **test)
{
    char *test1 = malloc(sizeof(char)*17);  
    strcpy(test1, "HEAP");

    *test = test1;

}

int main()
{
    char str[15]= "hello World";    //Array of char
    change(&str);   // Passing the address of my array of char
    printf("%s", str);
}

The goal is to change the address of strto the allocated memory array inside the function change

But changing the line :

char str[15]= "hello World"; 

to this (which is read only right ?):

char *str= "hello World"; 

Also, I'm getting a warning when compiling that I don't understand either :

main.c:17:12: warning: passing argument 1 of ‘change’ from incompatible pointer type [-Wincompatible-pointer-types]
   17 |     change(&str);   // Passing the address of my array of char
      |            ^~~~
      |            |
      |            char (*)[15]
main.c:5:20: note: expected ‘char **’ but argument is of type ‘char (*)[15]’
    5 | void change(char **test)

Thank you !

2
  • 1
    char str[15] isn't a pointer so you can't change its address. Do char orig[15]= "hello World"; char *str = orig; and then you'll be able to change what str points at. Commented Feb 28, 2022 at 1:37
  • That’s what I was trying to avoid using another pointer to achieve the same goal. Bu I was wrong and I think I get it now, thank you ! Commented Feb 28, 2022 at 14:16

2 Answers 2

3

char str[15] isn't a pointer so you can't change its address. You need str to be a char*.

Example:

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

#define HEAP "HEAP"

void change(char **test)
{
    char *test1 = malloc(sizeof HEAP); // sizeof(char) is defined to be 1
    strcpy(test1, HEAP);
    *test = test1;
}

int main()
{
    char orig[] = "hello World";
    char *str = orig;          // initialize it to point at the first char in orig
    printf("before: %s\n", str);
    change(&str);
    printf("after : %s\n", str);
    free(str);                 // free what you've allocated
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you, as I said I could have used a pointer to the array and directly modify it, but my bad I miss explained what I was trying to do. The thing was that an array cannot change address
@Liwinux "an array cannot change address" - Exactly! You're welcome!
Because if they do, then it’s stupid as we lost the allocated array during compilation right ?
@Liwinux Sort of I guess. All automatic (stack allocated) variables are fixed in memory. They are placed on the stack and then automatically removed when the stack unwinds.
That explains the lvalue then…
1

The goal is to change the address of strto the allocated memory array inside the function change...

You cannot change the address of a variable. If a variable is a non-const pointer, you can make it point to some other memory address, provided it should be of compatible type with the type of pointer.

Before moving ahead, a couple of points for array:

  • Arrays are not pointers. They both are different.
  • In C, array names are non modifiable lvalues.

The warning message that you are getting is very clearly conveying the message - the type of argument that you are passing to change() function is not compatible with type of its parameter. The type of &str argument (passing to change()) is char (*)[15] and type of test parameter is char **.

Lets change the type of test parameter of change() function and make it compatible with the type of &str that you are passing to change() function and check what happens!
Make the following change in your program

void change(char (*test)[15])
                 ^^^^^^^^^^^

With this change when you compile your program, you will get following error:

#  gcc -Wall -Wextra prg.c
prg.c:10:11: error: array type 'char [15]' is not assignable
    *test = test1;
    ~~~~~ ^
1 error generated.

The error is occurring because test is a pointer pointing to str array and when you dereference it (i.e. *test) you get the array of type char [15] and, that means, this statement will end up attempting to assign test1 to array of type char [15] (which, in this context, is array str). Check the second point above - array names are non modifiable lvalues. Hence, this error is occurring.

So, arrays are non assignable, however, you can change the content of array in change() function using the address of str that you passing to change() function. You can do:

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

#define NUM_CHARS 15

void change(char (*test)[NUM_CHARS]) {
    strcpy (*test, "HEAP");
}

int main (void) {
    char str[NUM_CHARS]= "hello World";    //Array of char

    printf ("Before calling change(), str : %s\n", str);
    change (&str);   // Passing the address of my array of char
    printf ("After calling change(), str : %s\n", str);

    return 0;
}

Output:

# ./a.out
Before calling change(), str : hello World
After calling change(), str : HEAP

Note, that same you can achieve with passing the str to change() function, instead of passing address of str (Of course, you have to make respective changes in the change() function as well).

How to make a pointer pointing so some other memory inside a function is already shown in other post (by @Ted Lyngmo).


Follow good programming practice:

  • Always check the malloc() return.
  • Make sure to free the dynamically allocate memory once done with it.

2 Comments

So because the array I a const pointer, I can’t change its address right ? Therefore it’s a non modifiable lvalue? So if I understand correctly an array is a different type of variable hence why I get a warning
I think that my problem was that for me writing char test[15] was kind of a shortcut to write char *test. But I was wrong. I guess it makes sense for it to be a non modifiable lvalue, because if we do then we actually lost the allocated array during the compilation process which is stupid. I actually don’t know what to write as a parameter to my function as I said that for me an array was a pointer, but now I get it, they are both two different type of variable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.