2

I understand that issues with string-reversal in C are numerous on this site, but I seem to be having a uniquely odd problem: the reversal logic simply does not run despite seeming to be set up correctly. I wanted to write a program to reverse a given string in-place, by moving two pointers from the front and back of the string together:

void reverse_inplace_pointer(char *string_in, int length) {
    char *back_ptr = string_in + (length - 1);

    for (int i = 0; i < length / 2; i++) {
        char swap_char = *back_ptr;

        /* Dereference pointers to double-check values */
        printf("\nCurrent front char: %c\nCurrent back char: %c", *string_in, *back_ptr);
        
        /* Swap */
        *back_ptr  = *string_in;
        *string_in = swap_char;
        printf("\nSwap %u successful.", i + 1);
    
        string_in++;
        back_ptr--;
    } 
}

Calling this with a test string: char *test_string = "TestMeTestMe"; nets the result:

Current front char: T
Current back char: e

And then execution just stops, at the assignment of the character pointed to by *string_in to the location pointed to by *back_ptr. If I remove the assignment, the program will quite happily move the pointers along the test string and print out each character without issue.

I looked for other examples of reassigning elements in arrays and found the logic in tutorials to be almost identical to mine. I copied this example wholesale as a test:

void steal_this_function(char *string) {
    printf("\nEntering function:");
    int length, c;
    char *begin, *end, temp;

    length = strlen(string);

    begin = string;
    end = string;

    for (c = 0; c < (length - 1); c++) {
        end++;
    }

    for (c = 0; c < length / 2; c++) {
        temp = *end;
        *end = *begin;
        *begin = temp;

        begin++;
        end--;
    }
}

The result is the same - it stops on the first iteration and the program exits. The only difference here is the reuse of the original pointer string, which is then walked to the end of the string with a for-loop.

Clearly I have some confusion here with pointers, but my understanding was that *back_ptr = *string_in; effectively says dereference the pointer string_in, then go to the location pointed to by back_ptr and store whatever it contains there.

I'm also compiling with the -Wall flag on GCC and it isn't finding any issues. This is frustrating because it should be very simple.

2
  • @user3121023 That should be the answer and not a comment :) Commented Aug 9, 2020 at 16:17
  • @user3121023 Ah, I can't believe that was it. It was a trivial issue, but if you want to copy your comment into an answer then I'll accept it. Cheers! Commented Aug 9, 2020 at 16:23

2 Answers 2

1

the function requires modifiable char array. It cannot be called when parameter is a pointer to thestring literal.

Some additional remarks.

  1. This kind of function should return the reversed string. It is possible to use it as a parameter of another functions.
  2. strlen returns size_t not int. Use the correct type in the loops as well
#include <string.h>
#include <stdio.h>

char *reverse(char *str)
{
    char *end = str + strlen(str) - !!*str;
    char *wrk = str;

    while(end > wrk)
    {
        char tmp = *wrk;
        *wrk++ = *end;
        *end-- = tmp;
    }
    return str;
}

int main(void)

{
    char str[] = "0123456789";

    printf("%s\n", reverse(str));
}
Sign up to request clarification or add additional context in comments.

5 Comments

char *end = str + strlen(str) - 1; produces an invalid pointer when str is an empty string. Comparing str and end has undefined behavior in this case an would indeed malfunction on some architectures such as 80286's large model with segmented pointers. You should use char *end = str + strlen(str);, while (str + 1 < end) and *wrk++ = *--end;.
@chqrlie disagree. Both pointers reference the same array. The comparison is defined per C standard.
I wrote the comment before you made the change. char *end = str + strlen(str) - !!*str; is a hideous hack with very poor pedagogical value (except for code golfing). Your suggesting the correct type size_t shows you care about teaching the right thing, so you could move the whole loop with initialization inside an if (*str) { ... }.
@chqrlie all string functions in the standard libraries do not check for NULL pointer and I am consistent with it
This has nothing to do with null pointers, but rather the empty string.
0

Calling this with a test string: char *test_string = "TestMeTestMe";

That's the culprit, as noted in the comments, it declares a pointer to the memory where the string literal "TestMeTestMe" is stored, which you are not allowed to modify.

You should declare an array instead.

char test_string[] = "TestMeTestMe"; // Now test_string is a modifiable
                                     // NULL-terminated char[13]

I'm also compiling with the -Wall flag on GCC and it isn't finding any issues.

-Wall it's not enough, but you can use -Wwrite-strings to catch this particular issue (see e.g. here).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.