Reputation: 145
I made a simple program to reverse a string in C. Here is my code:
#include <stdio.h>
int main(){
char istring[] = {'f','o','o','b','a','r'};
char revstring[sizeof(istring)];
for(int i = 0; i < sizeof(istring); i++){
int cplace = sizeof(istring)-i-1;
revstring[cplace] = istring[i];
}
printf("%s",revstring);
return 0;
}
and my result is, as expected raboof
.
Now, if I swap char istring[] = {'f','o','o','b','a','r'};
, with char istring[] = "foobar";
, I get nothing as my output. What's wrong?
Thanks in advance.
(Sorry if this is a total newbie question)
Upvotes: 2
Views: 95
Reputation: 26355
sizeof "foobar"
is 7, not 6. C strings are NUL terminated with the '\0'
character.
Your first example works because you fail to NUL terminate your string, and so the 'r'
and 'f'
swap. You're likely lucking out in that the address space following the reversed string evaluates to a zero (which equates '\0'
), terminating the string. Otherwise, printing a non-terminated string invokes undefined behaviour.
With "foobar"
, the 'f'
and '\0'
will be swapped, and your resulting C string will effectively be zero-length.
Solve this by using strlen
to get the length of a string, not sizeof
which gets the length of the block of memory. You'll need to include the string.h
header.
char str[] = "foobar";
size_t str_len = strlen(str);
char rev[str_len + 1];
rev[str_len] = '\0';
for (int i = 0; i < str_len; i++)
rev[i] = str[str_len - i - 1];
printf("%s\n", rev);
Upvotes: 4
Reputation: 223739
In C, a string is a null terminated array of characters. In your original program, istring
is not a string but an array of characters with no null byte at the end.
While you successfully reverse the characters, revstring
is not a string because there is no terminating null byte at the end. As such, when you attempt to print it as a string using the %s
format specifier for printf
, it searches past the end of the array. Reading beyond the bounds of an array is undefined behavior.
One of the ways undefined behavior can manifest itself is that the program appears to work properly. In your case, you got "lucky" and got the expected result.
When you define istring
as istring[] = "foobar";
you initialize it with a string constant which contains a null terminating byte. So this definition is actually one byte larger then the prior one.
When you reverse the characters, you're actually including the null byte. So the resulting array contains the null byte first followed by the other characters. Then when you print it, the null byte is seen first so what you have is an empty string.
In your loop, use strlen(istring)
instead of sizeof(istring)
as the upper bound. Then add the null byte at the end.
char istring[] = "foobar";
char revstring[sizeof(istring)];
for(int i = 0; i < strlen(istring); i++){
int cplace = strlen(istring)-i-1;
revstring[cplace] = istring[i];
}
revstring[strlen(istring)] = '\0';
If you define istring
as an array of characters, you need to allocate an extra byte to revstring
and keep sizeof
when checking the upper bound:
char istring[] = {'f','o','o','b','a','r'};
char revstring[sizeof(istring)+1];
for(int i = 0; i < sizeof(istring); i++){
int cplace = sizeof(istring)-i-1;
revstring[cplace] = istring[i];
}
revstring[sizeof(istring)] = '\0';
Upvotes: 3