Thread: Reversing a string declared as char[] works, but as char* it segfaults. Why?

  1. #1
    Registered User
    Join Date
    Oct 2022
    Posts
    2

    Question Reversing a string declared as char[] works, but as char* it segfaults. Why?

    Code:
    #include <stdio.h>
    
    void reverse(char* string, int length) {
        char otherString[length + 1];
        for (int i = 0; i < length; i++) {
            otherString[i] = string[length - i - 1];
        }
        otherString[length] = '\0';
        for (int i = 0; i < length; i++) {
            string[i] = otherString[i];
        }
    }
    
    int main() {
        //char* string = "ABCDE"; //this segfaults. Why?
        char string[] = "ABCDE";
        printf("Before: %s\n", string);
        reverse(string, 5);
        printf("After: %s\n", string);
        return 0;
    }
    Besides the, most certainly, not very performant string reversal function, I'm confused with the differences between passing a string param to reverse it. If I declare it as string[], it works just fine. But if I declared it as char*, it segfaults. Why is it?

    I welcome any resource that might document this further.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,631
    Code:
    char* string = "ABCDE";
    The above creates a const character string which can't be changed hence the segfault.

  3. #3
    Banned
    Join Date
    Jul 2022
    Posts
    112
    Your reverse function is not performant, it is a mess.

    1. You must declare the new array, right at the start,
    and not in a secondary function.
    Declaring an array in a secondary function forces you to use malloc() and free().

    2. You are attempting to change an array-literal in the second loop,
    this will always cause a segfault.

    3. Length - i - 1, this is so redundant.
    Declare another variable.

    4. There is no such thing as a string data-type in C,
    there is only null-terminated array.
    Last edited by kodax; 10-09-2022 at 08:34 PM.

  4. #4
    Banned
    Join Date
    Jul 2022
    Posts
    112
    Code:
    #include <stdio.h>
    
    int a_length(const char *);
    void a_reverse(char *, const char *, int);
    
    int a_length(const char *array) {
    
        int i = 0;
    
        while ('\0' != array[i]) {
            i = 1 + i;
    
        }
        
        return i;
    }
    
    void a_reverse(char *buffer, const char *array, int length) {
    
        int a = length;
        int b = 0;
    
        while (0 != a) {
            a = a - 1;
            buffer[b] = array[a];
            b = 1 + b;
    
        }
    
        buffer[b] = '\0';
        return;
    }
    
    
    int main(int argc, const char *argv[]) {
    
        int len = 0;
        char array[] = "1234";
        char new_array[64];
    
        len = a_length(array);
        a_reverse(new_array, array, len);
        printf("%s\n", new_array);
    
        return 0;
    }

  5. #5
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    900
    Quote Originally Posted by kodax View Post
    Code:
    int a_length(const char *array) {
    
        int i = 0;
    
        while ('\0' != array[i]) {
            i = 1 + i;
    
        }
        
        return i;
    }
    This function already exists in the Standard Library. It's called strlen().

    Quote Originally Posted by kodax View Post
    Code:
    void a_reverse(char *buffer, const char *array, int length) {
    
        int a = length;
        int b = 0;
    
        while (0 != a) {
            a = a - 1;
            buffer[b] = array[a];
            b = 1 + b;
    
        }
    
        buffer[b] = '\0';
        return;
    }
    This reverses a string but saves the reversed string to another array. The OP wants to reverse a string in-place (which is really quite simple).

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    1,047
    If it is to reverse a string "in place":
    Code:
    static inline void swap( char *p, char *q ) { char t = *p, *p = *q; *q = t; }
    
    char *strrev( char *p )
    {
      char *q = p;
      char *r = p + strlen( p ) - 1;
    
      while ( r > q )
        swap( r--, q++ );
    
      return p;
    }

  7. #7
    Banned
    Join Date
    Jul 2022
    Posts
    112
    1. "It's called strlen()."
    Wrong, OP needs to understand how strlen() works.

    2. "OP wants to reverse a string in-place (which is really quite simple)."
    You are misleading OP, reverse in-place is "hackish,"
    the right way is to use a new variable.

    3. @flp1969, Pointer-arithmetic is ugly.

    4. The last thing OP needs to worry about is "perfomant."
    OP is clueless.

    //char* string = "ABCDE";
    The "const" keyword is missing.

    //const char* string = "ABCDE";
    Last edited by kodax; 10-10-2022 at 07:25 PM.

  8. #8
    Registered User
    Join Date
    Sep 2020
    Posts
    395
    Quote Originally Posted by kodax View Post
    4. The last thing OP needs to worry about is "perfomant."
    OP is clueless.
    The OP is inexperienced. They already know this, and are trying to get some understanding. Stop being rude to them.

    And saying "pointer arithmetic is ugly" is silly - like saying "paint is ugly".

  9. #9
    Banned
    Join Date
    Jul 2022
    Posts
    112
    Pointer arithmetic is ugly, and this is true.

    Even if someone can understand your project,
    you do not realize that it is harder for them to read.
    And then, there are people who will discard your project out of frustration.

  10. #10
    Registered User
    Join Date
    Oct 2019
    Posts
    81
    Quote Originally Posted by kodax View Post
    Pointer arithmetic is ugly, and this is true.
    No it is not. Pointer arithmetic is syntactic sugar .

  11. #11
    Registered User
    Join Date
    Sep 2020
    Posts
    395
    Quote Originally Posted by ghoul View Post
    No it is not. Pointer arithmetic is syntactic sugar .
    syntactic sugar is syntax within a programming language that is designed to make things easier to read or to express.
    What are you saying it is 'syntactic sugar' for? Array indexing?

    I would argue the other way around - that arrays are sugar for pointer arithmetic + dereferencing...

    ...except arrays and pointers are subtilty different.

    If you can successfully predict the output of this code without running it, then you know what I mean.

    Code:
    #include <stdio.h>
    
    
    void func(char buffer[1000], char *ptr)
    {
        printf("In func() sizeof(buffer) is %zi\n", sizeof(buffer));
        printf("In func() sizeof(ptr) is %zi\n", sizeof(ptr));
    }
    
    
    int main(void)
    {
        char buffer[1000];
        char *ptr;
    
    
        ptr = buffer;
        printf("In main() sizeof(buffer) is %zi\n", sizeof(buffer));
        printf("In main() sizeof(ptr) is %zi\n", sizeof(ptr));
        func(buffer, ptr);
        return 0;
    }
    Go on... give it a try. What will the question marks be?

    Code:
    In main() sizeof(buffer) is ?
    In main() sizeof(ptr) is ?
    In func() sizeof(buffer) is ?
    In func() sizeof(ptr) is ?
    it can't be pure sugar if it tastes differently (pointers and arrays, that is).

    It's why it is said "arrays decay to pointers" not "arrays are pointers".
    Last edited by hamster_nz; 10-11-2022 at 03:35 AM.

  12. #12
    Registered User
    Join Date
    Feb 2019
    Posts
    1,047
    Quote Originally Posted by kodax View Post
    Pointer arithmetic is ugly, and this is true.

    Even if someone can understand your project,
    you do not realize that it is harder for them to read.
    And then, there are people who will discard your project out of frustration.
    I would discard a buggy version or a version which requires too many arguments to be assumed "right". Like this:
    Code:
    // Assumes buffer and array to be valid pointers (and not overlapping)
    // and assumes length >= 0 (can be negative, you know?).
    void a_reverse(char *buffer, const char *array, int length) {
    
     
    
        int a = length;
    
        int b = 0;
    
     
    
        // ignoring the lines above, what is 'a' and what is 'b'?
        // your code can be huge.
        while (0 != a) {
    
            a = a - 1;
    
            buffer[b] = array[a];
    
            b = 1 + b;
    
     
    
        }
    
     
    
        buffer[b] = '\0';
    
    
        // why 'return' when you are already at the end of the function scope?
        return;
    
    }

    And pointer arithmetic is beautiful (and so are arrays indexes).

    Anyway... this is also wrong:
    Code:
    int main( int argc, const char *argv[] ) {
    Who's saying? ISO 9899!

  13. #13
    Registered User
    Join Date
    Feb 2019
    Posts
    1,047
    My vresion for 'not inplace' reversal:
    Code:
    // Using restrict to tell the compiler the pointers cannot be the same.
    // Yep... assumes both pointers are valid (notice: no 'length'!).
    char *strrev( char * restrict out, const char * restrict in )
    {
      // points out to the end of the buffer and puts a '\0' there.
      out += strlen( in );
      *out-- = '\0';
    
      //  while '\0' isn't found yet, copy chars in reverse order,
      // incrementing the input pointer, and decrementing the output pointer.
      while ( *in ) *out-- = *in++;
    
       // puts out back at the beginning and return it.
      return ++out;
    }
    Last edited by flp1969; 10-11-2022 at 04:57 AM.

  14. #14
    Banned
    Join Date
    Jul 2022
    Posts
    112
    Unsequenced modification and access to "out" !
    Code:
    *out-- = '\0';
    Everything in 1 line, you are trying to save space ? No brackets ?
    Code:
    while ( *in ) *out-- = *in++;
    Your example is considered terrible practice.
    Code can be huge, but at least it is clear.
    People reading this know that I am right.

    Guess what, unreadable code resembles poor handwriting.
    Similarly, if you mumble during your speech,
    you will not only frustrate your listener which is selfish,
    but in the end, no one will be able to understand you.

  15. #15
    Registered User
    Join Date
    Feb 2019
    Posts
    1,047
    Keep trying... one day you'll be able to deal with pointers!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 11
    Last Post: 06-16-2011, 11:59 AM
  2. Replies: 2
    Last Post: 09-12-2010, 09:15 AM
  3. char causes segfaults more than strings?
    By TheBigOnion in forum C++ Programming
    Replies: 3
    Last Post: 03-30-2010, 10:07 AM
  4. Reversing (char)...
    By yaya in forum C++ Programming
    Replies: 7
    Last Post: 05-27-2007, 04:15 AM
  5. I declared it as int but it shows up as an char...
    By XR3D403 in forum C Programming
    Replies: 5
    Last Post: 02-10-2003, 09:12 AM

Tags for this Thread