0

I am using the reverse function.

void reverse(char s[]) {
    int i, j;
    char c;
 
    for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
        c = s[i]; 
        s[i] = s[j];
        s[j] = c;
    }
}

If I pass a string of type char a[] = "abcd" then I get on the output dcba.

But if I pass char *a = "abcd" the I get bus error.

Can I somehow reverse the string exactly of type char *?

Source code:

#include <stdio.h>
#include <string.h>

void reverse(char s[]);

int main() {
    char a* = "abcd";
    reverse(a);
    printf("%s", a);
}

void reverse(char s[]) {
    int i, j;
    char c;
 
    for (i = 0, j = strlen(s) - 1; i < j; i++, j--) { 
        c = s[i]; 
        s[i] = s[j];
        s[j] = c; 
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Andrey
  • 21
  • 2
  • 3
    https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s?rq=1 – Mat May 03 '22 at 09:23
  • 3
    @Andrey You may not change a string literal. Any attempt to change a string literal results in undefined behavior. – Vlad from Moscow May 03 '22 at 09:29
  • May I suggest `void revprint(const char *s) { for (size_t i = strlen(s); i-- > 0; ) putchar(s[i]); }` – pmg May 03 '22 at 09:31

2 Answers2

3

There are no strings of type char *. A string is a sequence of characters terminated with the zero-character '\0'.

In this declaration (that has a typo char a* = "abcd";)

char *a = "abcd";

there is declared a pointer to a string literal. The string literal itself has the type char[5]. But used as an initializer expression it is implicitly converted to a pointer to its first element of the type char *.

And you are trying to change the string literal pointed to by the pointer within the function reverse.

However you may not change a string literal. Any attempt to change a string literal results in undefined behavior.

From the C Standard (6.4.5 String literals)

7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

What you could do is to create a new string that will store characters of the source string literal in the reverse order.

For example

char * reverse_copy( const char *s )
{
    size_t n = strlen( s );

    char *t = malloc( n + 1 );

    if ( t != NULL )
    {
        t += n;
        *t = '\0';

        while ( *s ) *--t = *s++;
    }

    return t;
}

And the function can be called like

char *s = "abcd";
char *p = reverse_copy( s );
if ( p != NULL ) puts( p );
free( p );

Here is a demonstration program.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

char *reverse_copy( const char *s )
{
    size_t n = strlen( s );

    char *t = malloc( n + 1 );

    if (t != NULL)
    {
        t += n;
        *t = '\0';

        while (*s) *--t = *s++;
    }

    return t;
}

int main( void )
{
    char *s = "abcd";

    char *p = reverse_copy( s );
    if (p != NULL) puts( p );

    free( p );
}

The program output is

dcba
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

Your reverse function is ok. The problem is that you instantiated you string as a literal by doing so: char *a = "abcd"; (it's '*a' not 'a*' btw)

You cannot modify string literals. To test your function you could do so:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void reverse(char s[]);

int main(){
    char *a = malloc(sizeof(char) * 5);
    if (a == NULL)
        return 1;
    a[0] = 'a';
    a[1] = 'b';
    a[2] = 'c';
    a[3] = 'd';
    a[4] = '\0';
    reverse(a);
    printf("%s", a);
    free(a);
}

void reverse(char s[]){
     int i, j;
     char c;

     for (i = 0, j = strlen(s) - 1; i<j; i++, j--) {
         c = s[i];
         s[i] = s[j];
         s[j] = c;
     }
}
Eron
  • 134
  • 3