理解字符串和数组

时间:2013-05-20 14:13:28

标签: c arrays string pointers

考虑这段代码。

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
}

有两个字符串st。首先,我将s设置为"foo",然后将t指向s。当我打印字符串时,我得到foo foo

然后,将"bar"复制到s并再次打印,我得到bar bar

为什么t的值会在这种情况下发生变化? (我将"bar"复制到s为什么t更改了。


现在我将strcpy(s, "bar")更改为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
}

此代码为我提供了foo foobar foo

为什么在这种情况下没有改变?

3 个答案:

答案 0 :(得分:12)

这是undefined behaviour,这意味着任何事情都可能发生:

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

因为strcpy()正在写入内存中的随机位置,因为s是未初始化的指针。


编辑后纠正未定义的行为

  

问题1 - 在这种情况下,为什么t的值会发生变化? (我复制了“bar”,为什么没有改变)。

这是一个指针赋值:

t = s;

并导致ts指向同一内存malloc()且之前已分配给s的内存。通过ts可以看到对该内存的任何更改。

  

问题2 - 为什么在第二种情况下不改变?

这会将字符串文字"bar"的地址指定给s

s = "bar";

所以现在ts没有指向相同的内存位置。 t指向早先malloc()并分配给s的内存(由于t = s;指针分配)。

strcpy()= 非常不同:

  • strcpy()将字符复制到其第一个参数
  • 指定的内存地址
  • 赋值,=,更改指针所包含的地址

答案 1 :(得分:2)

strcpy(s, "foo");

foo复制到s指向的内存位置     t = s; 现在,ts都指向同一位置 因此,相同的输出

现在,您将bar复制到s。由于ts都指向同一位置。因此,再次输出相同的数据。


这条线上的一切都是一样的

s = "bar"

您创建一个字符串常量bar。并将其地址分配给s。它是一个pointer它可以指向任何内存位置。不一定是原来的。

现在,

s指向bart仍然指向它在开头指向的早期位置,因此输出

答案 2 :(得分:2)

一种简单的理解方式如下: -

      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

现在仍然指向地址123,这就是为什么t,s都打印条形码。

       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     

现在s将包含地址321,而t具有值123,这就是s和t给出不同值的原因。