C char * question

This is an absolute question about noob, but I don't seem to find a suitable answer anywhere, so here it goes, given this code:

#include <stdio.h> #include <stdlib.h> void initialize( char * buffer) { buffer = malloc(1); *buffer='a'; } int main(void) { char * buff; buff = malloc(sizeof(char)); *buff = 'b'; initialize(buff); puts("Contents of buffer are: "); puts(buff); return 0; } 

The output of main is always "b", which is really strange for me. I thought that by passing the pointer for initialization I could change the value of the pointer declared basically, but for some reason, it seems to be passing the variable by value, and when I return, I have the values ​​specified in the main, with " ",

I would like to know why this is ... should I pass a pointer reference instead? something like char * & ??

Regards, Alex

+4
source share
6 answers

The first thing you do in your function is to reassign another memory location to buffer using the new malloc . Then you change this new memory location, but the buff in the main function does not change, because it still points to the old location.

If you remove malloc, it will work:

 void initialize( char * buffer) { *buffer='a'; } 

Now we are modifying the original memory cell.

+5
source

You need to change the initialize() function to take a pointer to your buffer and pass the address of the pointer. Although it receives the buffer that you are going to, you cannot change what buff points to this path. Just keep in mind that in this case you will have a memory leak and you won’t be able to print the contents as a string, since it does not have zero completion.

 void initialize(char **buffer) { *buffer = malloc(sizeof(char)); **buffer='a'; } int main(void) { char *buff; buff = malloc(sizeof(char)); *buff = 'b'; initialize(&buff); puts("Contents of buffer are: "); printf("%c\n", *buff); return 0; } 

Responses to comments below:

I don’t understand why a pointer to a pointer is needed ... does this look like a link in C ++?

When I read your code, I thought you wanted to change what the buff pointer (in main() ) points to, a new buffer. I thought that when I saw that you assigned a new buffer in your initialize() function. To be able to change the value of a variable from another location (or function), you will need the address of this variable. Since it was originally a char * character pointer, you would need a pointer to that character pointer, char ** . And yes, it looks like a C ++ link, only more verbose.

So, can I change the value of the passed variable?

If you intended to simply modify the contents of the buffer that was passed, Krtek covers this. All you had to do was discard the new buffer allocation and change what the buffer points to.

 void initialize(char *buffer) { /* *buffer = malloc(sizeof(char)); */ /* do not need this */ /* modify the buffer that was passed in */ *buffer='a'; } 

Regarding memory leak problem

In fact, a memory leak was caused by allocating a new buffer without freeing up previously allocated memory. You really had this:

 char *buff = malloc(sizeof(char)); /* allocate some memory */ buff = malloc(sizeof(char)); /* oops, memory leak */ 

do you mean using puts with a non-null terminating string? That is why you are using printf ("% c \ n", * buff)? making the string end with \ n?

That was another problem. puts() takes a line with a terminating zero and prints it to standard output, followed by a new line. This would not be a memory leak for printing potentially garbage text, it is just ... something else. Your buffer contained only space for one character (no null terminator). Therefore, you should not use puts() to print the contents of the buffer. You must print only one character. Using printf() with '\n' should have led to the same output behavior as puts() .

+1
source

In case a fragment without memory errors is preferred, here are a few alternatives to what has already been published, more applicable to programming in the real world.

Note that the same “code module” that mallocs should also release. Do not do malloc in one module and free yourself in another, this is a very bad practice!

Version 1:

 #include <stdio.h> #include <stdlib.h> void set (char* buffer) { *buffer='a'; } int main (void) { char* buff; buff = malloc(sizeof(char)); /* main allocates */ *buff = 'b'; set (buff); puts("Contents of buffer are: "); printf("%c", *buff); /* don't use puts on single characters! */ free(buff); /* main cleans up its own mess */ return 0; } 

Version 2:

 /* main.c */ #include <stdio.h> #include <stdlib.h> #include "my_functions.h" int main (void) { char * buff; buff = malloc(sizeof(char)); *buff = 'b'; alloc_and_set (&buff); puts("Contents of buffer are: "); printf("%c", *buff); cleanup(); return 0; } 

my_functions.h

 #ifndef MY_FUNCTIONS_H #define MY_FUNCTIONS_H void alloc_and_set (char** buffer); void cleanup (void); #endif /* MY_FUNCTIONS_H */ 

my_functions.c

 #include "my_functions.h" static char* internal_buffer = NULL; /* used to keep track of allocated data */ void alloc_and_set (char** buffer) { if(internal_buffer == NULL) /* make function memory leak proof */ { internal_buffer = malloc(sizeof(char)); } *internal_buffer = 'a'; *buffer = internal_buffer; } void cleanup (void) { free(internal_buffer); /* my_functions module cleans up its own mess */ internal_buffer = NULL; } 
+1
source

You have changed the copy of the pointer to a point elsewhere, but your real pointer does not indicate this. If you are not using your code to work, use this function.

 void initialize( char ** buffer) { *buffer = malloc(1); **buffer='a'; } 

then call initialize(&buff);

0
source

When you do it

 buffer = malloc(1); 

The buffer variable passed from the main one does not change because it was passed by value.

If you write this:

 void initialize( char **buffer) { *buffer = malloc(1); **buffer='a'; } 

Then you will see the change.

Edit1: you need to understand the * operator. buffer is a pointer in itself. * buffer is actually the location that the buffer points to, and changing it does not affect the actual buffer.

0
source
 void initialize( char * buffer) { // buffer is a local pointer to this function which will have // same value as buff in main AT THIS POINT. // now you call malloc to allocate memory and make buffer // point to that memory. So the value of buffer got changed now. // buff in main remains unchanges. buffer = malloc(1); // now you write to the memory allocated. *buffer='a'; // key point is buff in main is still pointing where it was. } int main(void) { // buff is now a wild pointer. char * buff; // now you allocate memory using malloc and make buff point to that memory. buff = malloc(sizeof(char)); // you write to the memory pointed to by buff. *buff = 'b'; // you pass buff BY VALUE to the function initilize. initialize(buff); // since a copy of buff (buffer) was changed, buff still points // to a memory that has b in it. puts("Contents of buffer are: "); puts(buff); return 0; } 

If you want the called function to affect the value of buff , you need to pass its address:

 void initialize( char ** buffer) { *buffer = malloc(1); **buffer='a'; } 

and name it like:

 initialize(&buff); 

but note that this will result in a memory leak allocated in main. Since you have already allocated the main memory, you can simply remove malloc:

 void initialize( char * buffer) { *buffer='a'; } 
0
source

Source: https://habr.com/ru/post/1343738/


All Articles