ShuklaSannidhya
ShuklaSannidhya

Reputation: 8976

Understanding strings and arrays

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?

Upvotes: 3

Views: 300

Answers (3)

birubisht
birubisht

Reputation: 908

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 .

Upvotes: 2

hmjd
hmjd

Reputation: 121971

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

Upvotes: 12

Suvarna Pattayil
Suvarna Pattayil

Reputation: 5239

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

Upvotes: 2

Related Questions