2

So I'm trying to reverse a string, but I get a memory fault. Memory for s and s1 is initialized enough to accomodate the '/0' character as well.

Interestingly if I remove *s=*s1 and print s1 instead the program works. But I haven't even set the "\0" character at the end of s1 so how does it even know where to stop printing?

And in the case below what exactly is the issue?

#include <stdio.h> #include <string.h> #include <stdlib.h> void main(void) { char *s = "abcdefghijklmnop", *s1=malloc(17); int i; for(i=0;i<strlen(s);i++) { *(s1+i) = *(s+strlen(s)-1-i); } *s=*s1; printf("%s",s); } 
5
  • 1
    What do you think the difference between *s = *s1 and s = s1 is? Commented Sep 28, 2017 at 12:10
  • the former takes the value s1 points to and puts it in the address s points to, while the latter makes s point to what s1 points to Commented Sep 28, 2017 at 12:12
  • @ScottHunter: Okay I see why that should work. But what's wrong in *s = *s1 Commented Sep 28, 2017 at 12:15
  • you cannot write into memory associated with *s. Commented Sep 28, 2017 at 12:16
  • 1
    Every time you feel like writing *(p + i) for some pointer p and index i, just write p[i] instead. It's much easier to read, and means the exact same thing. Commented Sep 28, 2017 at 12:24

2 Answers 2

3

The char *s = "abcdefghijklmnop" is a string literal which is often in read-only memory. An error will be generated if you attempt to modify a string literal.

You attempt to replace the first character in s with the first character in s1 when you do *s=*s+1.

If s wasn't a string literal, you should've done s=s1 instead of *s=*s1 to make s its reverse.

More about this:

https://softwareengineering.stackexchange.com/questions/294748/why-are-c-string-literals-read-only
String literals: Where do they go?
where in memory are string literals ? stack / heap?

The correct string is printed with printf("%s", s1); even if no \0 was stored because the memory next to the last character just happened to be 0 which is equivalent to \0. This needn't always be so and cannot be relied upon as malloc() doesn't initialise the memory that it allocates.

But calloc() will initialise the memory it allocates to 0.

See more here.

Sign up to request clarification or add additional context in comments.

5 Comments

Ok, so actually *s = *s1 only replaces the first character? Not the entire string?
@CodeChef123 That's right. If s wasn't a string literal and could be modified, you should've done s=s1. And don't forget to deallocate the memory for s1 with free(s1).
So you're saying the address s is pointing to is in ROM? Is there any reason for this, as it seems more logical for it to be like a normal pointer(*ints, for e.g.)
And for the 2nd part of my question if I remove *s=*s1 and print s1 how does the program know when to stop printing because I haven't supplied the \0 character
About the first part, see links in the answer I just added. About the second part, the memory adjacent to the last character probably just happened to be 0 which is equivalent to \0 denoting the end of string. You cannot rely on this as malloc() won't initialise the memory it allocates. But calloc() will initialise its memory with 0.
0

In your code *s=*s1 only copy the first content of s1 into s. i.e, *(s+0)=*(s1+0) not the entire string. So we need to assign the address of s1 to s. i.e, s=s1.

#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char *s = "abcdefghijklmnop", *s1=malloc(17); int i; for(i=0;i<strlen(s);i++) { *(s1+i) = *(s+strlen(s)-1-i); } s=s1; printf("%s",s); free(s1); return 0; } 

It is good practice to free the memory after its use.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.