3

I am trying to reverse a string in-place using two pointers to the same string. First one(char *p) points to the starting location of the string and second one(char *q) points to the ending location of the string. So when I tried to debug using gdb, I get am getting segmentation fault at line 16.

When I tried to print the values of *p and *q, it works fine. Why am I getting segfault while I'm still able to access those location?

Breakpoint 1, main () at reverse.c:16
16          *q = *p;
(gdb) print p
$1 = 0x5555555547e4 "hello"
(gdb) print q
$2 = 0x5555555547e8 "o"
(gdb) step

Program received signal SIGSEGV, Segmentation fault.
0x00005555555546db in main () at reverse.c:16
16          *q = *p;

The actual code of the program is

#include<stdio.h>

int main() {
    char *array = "hello";

    char *p=&array[0];// pointer to the first element

    // Make q point to last value of the array
    char *q = &array[0];
    while(*q) q++; 

    char temp;
    q--; // move left so that we don't point to `\0`
    while(p<q){ 
        temp = *p;
        *q = *p;
        *p = temp; 
        p++;q--;    
    }

    printf(" Done reversing \n");
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

2 Answers2

6

Your string, which you call array, is not really a char array, but a string literal, which is, depending on the platform, not writable. So change it to

char array[] = "Hello";

There is a difference between char *array = "string" and char array[] = "string".

  • char *array = "string" puts "string" in read-only parts of the memory, and makes array point to it. Thus, any attempt to change the contents of the memory array is pointing to will result in a seg fault (illegal in other words).
  • char array[] = "string" puts "string" in the read-only parts of the memory and copies it to a newly allocated memory on the stack where array is pointing to. Thus, making changes to the memory array is pointing to legal.

You also might want to take a look at this post.

Giorgi Aptsiauri
  • 355
  • 1
  • 2
  • 11
Karsten Koop
  • 2,475
  • 1
  • 18
  • 23
2

You are trying to change the string literal

char *array = "hello";

pointed to by the pointer array.

Though in C (opposite to C++) string literals have types of non-constant character arrrays nevertheless you may not change string literals. Any attempt to change a string literal results in undefined behavior.

You should declare a character array initializing it with the string literal. For example

char array[] = "hello";

Here is a demonstrative program.

#include <stdio.h>

int main(void) 
{
    char array[] = "hello";

    puts( array );

    char *q = array;
    while ( *q ) ++q;

    for ( char *p = array; p < --q; ++p )
    {
        char c = *p;
        *p = *q;
        *q = c;
    }

    puts( array );

    return 0;
}

Its output is

hello
olleh

Also the code snippet in your program that swaps characters is wrong

    temp = *p;
    *q = *p;
    *p = temp; 

There must be

    temp = *p;
    *p = *q;
    *q = temp; 

And as the variable temp is used only within the while loop its declarative region should be restricted by the block scope of the while loop.

while(p<q){ 
    char temp = *p;
    *p = *q;
    *q = temp; 
    p++;q--;    
}

Take into account that according to the C Standard the function main without parameters shall be declared like

int main( void )
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335