3

Consider this code.

int main()
{
    char *s, *t;

    s = malloc(4 * sizeof(char));
    strcpy(s, "foo");
    t = s;
    printf("%s %s\n", s, t);         // Output --> foo foo
    strcpy(s, "bar"); // s = "bar"
    printf("%s %s\n", s, t);         // Output --> bar bar
}

There are 2 strings s and t. First I set s to "foo" and then make t point to s. When I print the strings, I get foo foo.

Then, copy "bar" tos and print again, I get bar bar.

Why does value of t changes in this case? (I copied "bar" to s why did t change).


Now when I change strcpy(s, "bar") to s = "bar" -

int main()
{
    char *s, *t;

    s = malloc(4 * sizeof(char));
    strcpy(s, "foo");
    t = s;
    printf("%s %s\n", s, t); // Output --> foo foo
    s = "bar"
    printf("%s %s\n", s, t); // Output --> bar foo
}

This code gives me foo foo and bar foo.

Why didn't it change in this case?

2
  • 3
    Moderator Note: Play nice. Keep the comments on topic (meaning they should be asking for clarification). If you want to open a discussion about the merits of this question, go here. Commented May 20, 2013 at 18:19
  • 1
    I have removed the second part of your question, if you still want to ask it, make a separate post. You should ask only one question per post. Commented May 22, 2013 at 7:32

3 Answers 3

12

This is undefined behaviour, which means anything can happen:

char *s, *t;
strcpy(s, "foo");

as strcpy() is writing to a random location in memory because s is an uninitialised pointer.


(after edit that corrected undefined behaviour)

Question 1 - Why does value of t changes in this case? (I copied "bar" to s why did t change).

This is a pointer assignment:

t = s;

and results in both t and s pointing to the same memory that was malloc() and assigned to s earlier. Any change to that memory is visible via both t and s.

Question 2 - Why isn't t changing in the second case?

This assigns the address of the string literal "bar" to s:

s = "bar";

so now t and s do not point to the same memory location. t points to the memory that was earlier malloc() and assigned to s (because of the t = s; pointer assignment).

strcpy() and = are very different:

  • strcpy() copies characters to the memory address specified by its first argument
  • assignment, =, changes the address which a pointer holds
Sign up to request clarification or add additional context in comments.

6 Comments

Ok, I have malloced now... still the same problem.
And why didn't it change in the 2nd case?
So whenever I create a string literal, it creates a new location in the memory? Like s = "bar", would first create a "bar" in a new location and then assign it to s?
@ShuklaSannidhya, basically yes. String literals will be stored, in a read-only location, as part of binary produced during compilation.
@ShuklaSannidhya, that is because x is not a pointer. A pointer of any type stores a memory address.
|
2
strcpy(s, "foo");

Copies foo to memory location pointed to by s t = s; Now, t and s both point to same location Hence, same output

Now, you copy bar to s. Since both t and s point to same location. Hence, same output again.


Upto this line everything is same

s = "bar"

You create a string constant bar. And assign its address to s. Its a pointer it can point to any memory location. not necessarily the original one.

Now,

s points to bar and t still to the earlier location it pointed to in the beginning and hence the output

Comments

2

a simplistic way to understand could be as follows :-

      s = malloc(4 * sizeof(char));    // this will be interpreted as follows 
      s = 123 ------------>|   |   |   |   | //some garbage values at these location
                           123  124 125 126   // some random address chosen.

      strcpy(s, "foo") ; // it copies at the address provided by s i.e.
                             |'f'|'o'|'o'|'\0'|
                              123 124 125  126 

      t = s;      this statement means t it pointing to address = 123

      strcpy(s, "bar"); // this statement copies at given address it means it will   override previous value .   i.e
                            |'b'|'a'|'r'|'\0'|
                             123 124 125 126

now t still pointing to address 123 that is why t, s both prints bar .

       s = "bar"  // this will  assign a new address to s which is base address of "bar" string . i.e .          
                           |'b'|'a'|'r'|'\0'|
                            321 322 323 324     

now s will contain address 321 while t has value 123 that is why s and t are giving different values .

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.