简体   繁体   中英

C: Can reverse array of chars, but not string

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)

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);

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';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM