I am creating a char array (representing a string) and adding characters to the array from the end of the array. But I don't know how many characters I will be adding in total ahead of time.
Once I have finished adding all the characters I need, I want to advance the pointer so that it points to the start of the string. But I am unable to free the pointer after doing so.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char* getGreeting() {
// Allocate a 0-initialized buffer that fits 10 characters
char* res = (char*) calloc(10, sizeof(char));
// Write some characters into the array from the end
res[4] = 'H';
res[5] = 'e';
res[6] = 'l';
res[7] = 'l';
res[8] = 'o';
res[9] = '\0';
// Move the pointer along until it gets to the first non-null character
while (*res == '\0') {
res++;
}
// Printing out each character to see what's going on
int i = 0;
while (res[i] != '\0') {
printf("c[%d]: %c\n", i, res[i]);
i++;
}
printf("c[%d]: \\0\n", i);
// Print out the string to see what's going on
printf("res: %s\n", res);
// Return the pointer that may have been advanced
return res;
}
int main() {
char* greeting = getGreeting();
// Trying to free the memory pointed to by the pointer
free(greeting);
return 0;
}
This is the printed output:
c[0]: H
c[1]: e
c[2]: l
c[3]: l
c[4]: o
c[5]: \0
res: Hello
free(): invalid pointer
How can I create a string that I don't know the length of beforehand? Or, alternatively, how do I correctly shorten a string that was populated from the end of the char array?
The problem I was originally trying to solve
I am learning C and doing some coding challenges to get familiar with the language. This particular challenge came from having to add two large numbers that are given as strings (represented as decimal). I add the right-most digits, store the unit-digit to the end of the char array, carry the tens-digit over, and repeat with the next digit. That's why I populate the string from the end.
First of all, to quote this answer:
Once you have advanced a pointer from its beginning,
freecannot free the memory anymore. This is because most implementations store some meta-information about the size of the block in the address(es) "before" the address pointed to by the pointer returned frommallocorcalloc. If you advance the pointer and return it,freedon't see that metadata "before" this new address, and don't know how much memory it needs/can free. See the answers to How does free know how much to free? for more details/discussion.What you need to do is to allocate a new block of memory once you know the correct size, copy the characters from the old char array into the new char array, free the original block of memory, and then return the pointer to the new block of memory.