Reputation: 33813
I have two ways to do the same purpose, the first-way prints unknown symbols and the second-way prints exactly what I want.
The first-way:
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr) + 1), *p = str;
while (*constStr) {
*p = *constStr;
constStr++;
p++;
}
printf("%s\n", str);
free(str);
The result:
The second-way:
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr) + 1);
for (int i = 0; i <= strlen(constStr); i++) {
str[i] = constStr[i];
}
printf("%s\n", str);
free(str);
The result:
Why the first-way the result seems strange?
Upvotes: 2
Views: 449
Reputation: 30926
No you didn't null terminate the string. This is undefined behavior to pass pointer to non-null terminated char array in printf
using %s
format specifier.
Outside the loop make *p=0
. That will null terminate the char array.
Second way is printing because you copied the \0
which is in strlen(constStr)
index of the array. Notice the <=
in the loop condition.
From where those weird letters come?
Think in terms of printf
. When it sees the %s
format specifier it prints starting from the address provided to it as argument. Now when does it stop? when it finds the \0
. here it didnt find it and it read out of the memory that you allocated. Those bit patterns on those memory turned out to be those non printable characters. That's what you saw. The correct way to do this would be:
const char *constStr = "Hello world";
char *str = malloc(strlen(constStr) + 1), *p = str;
while (*p++ = *constStr++); // here `\0` will be copied.
printf("%s\n", str);
free(str);
When working with strings make sure you keep the corner cases clean. By that I mean,check whether the \0
is copied or not etc. This is so common a problem when we implement string routines.
Upvotes: 1
Reputation: 43128
To fix the first one, add a null at the end of the string:
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr) + 1), *p = str;
while (*constStr) {
*p = *constStr;
constStr++;
p++;
}
*p = '\0'; /* <-- HERE */
printf("%s\n", str);
free(str);
Note: you are modifying a pointer to a temporary - not recommended. Use the same approach as you did for str
, by using a another pointer which gets shifted.
Upvotes: 1