C char pointer versus pointer to char array, increasing dynamic allocation

I'm new to C, and it's hard for me to understand the reason why the code block below doesn't work.

#include <stdio.h> #include <stdlib.h> int main() { char *src = "http://localhost"; /* THIS WORKS char scheme[10]; char *dp = scheme; */ //DOESN'T WORK char *dp = malloc(10); while (*src != ':') { *dp = *src; src++; dp++; } *dp = '\0'; /* WORKS puts(scheme) */ //DOESN'T WORK puts(dp); } 

Expected Result: http on stdout. In both cases, dp must be a pointer to an array of char pointers (char **) . However, when using the malloc method, it does not print anything. I ran the code through GDB, and my src and dp erased 1 character at a time. If I wrap a while in a function call, it works. I realized that the reason is that the parameters are evaluated as a copy. However, then I read that arrays are an exception and passed as pointers. Now I am confused. I can get around this, but I'm trying to understand why this method does not work.

+6
source share
4 answers

You change dp inside the loop

 dp = malloc(10); 

let's say dp has a value of 0x42000000

 while () { dp++; } 

let's say that the cycle went 4 times, so dp has the value 0x42000004

 *dp = 0; 

now you put the null character at the address pointed to by dp

 puts(dp); 

and then you try to print this null :)

Save dp and print the saved value

 dp = malloc(10); saveddp = dp; /* ... */ puts(saveddp); free(saveddp); /* for completeness */ 

It works with scheme , because scheme is an array, and you cannot change this address!

+10
source

After the loop ends, dp points to the end of the highlighted line. You need to save dp immediately after malloc and increase the copy, not the original pointer to the beginning.

+4
source

Before starting the cycle, dp indicates the beginning of the allocated memory. At each iteration, you copy the character indicated by src to the current dp position and go to one memory location that dp points to. At the end of the loop, dp points to the memory location immediately after the p character, where you assigned '\0' . When you try to print a line using puts (dp) because the contents of dp changed and now point to the location immediately after copying the last character, it will start printing from that place. It will print an empty line, since the very first location dp points to is a null character.

Before the cycle

 +----------+ | src | +----------+ | | V +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ | h | t | t | p | : | / | / | . . . ? | ? | +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ +----------+ | dp | +----------+ | | V +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ | | | | | | | | . . . | | +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ 

After the loop (with dp = malloc (10))

  +----------+ | src | +----------+ | | V +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ | h | t | t | p | : | / | / | . . . | ? | +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ +----------+ | dp | +----------+ | | V +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ | h | t | t | p | \0 | | | . . . | | +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ 

Note puts (dp) will start printing print from the above location. This will not give the expected result. Also, since you did not save the original dp address that you actually allocated. You cannot recover from a cycle.

After the loop (with dp = & circuit)

  +----------+ | src | +----------+ | | V +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ | h | t | t | p | : | / | / | . . . | ? | +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ +----------+ | dp | +----------+ | | V +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ scheme[ | h | t | t | p | \0 | | | . . . | | ] +-----+-----+-----+-----+-----+-----+-----+---- ----+----+ puts (scheme) will work because it still refers to the base of the array puts (dp) will not work because it does not point to the base of the array and currently points to a location pointing to null character 

The above commented solution works because you use the scheme array to print the string. scheme refers to the array you want to print, and scheme refers to the base address of the array because you did not modify it (and you cannot change it). That's why it starts from the base and prints to the '\0' that you assigned after the loop.

You can either do

  int i; for (i=0; (src[i] != ':') && (src[i] != '\0'); i++) { dp[i] = src[i]; } 

or follow below

  char *dp_bak; char *dp = malloc(10); dp_bak = dp; /* Backup the base address */ while (*src != ':') { *dp = *src; src++; dp++; } *dp = '\0'; dp = db_bak; /* Restore the base address */ puts (dp); 
+2
source

In fact, as stated above, the "schema" was your pointer to the beginning of the line, and dp was your iterator.

char * scheme = malloc (10), * dp = scheme;

...

put (scheme);

-2
source

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


All Articles