简体   繁体   English

关于 c 处理字符串的方式的困惑

[英]confusion about the way c handles strings

why wouldn't为什么不

   char *name = "asd";
   printf("%p\n%p", (void *)&name, (void *)&name[0]);

give the same output as给出相同的输出

char name[] = "asd";
printf("%p\n%p", (void *)&name, (void *)&name[0]);

i've read that c takes strings as a pointer to their first char, till it reaches the \\0 but the code above doesn't like it, so it confusing for ac beginner我读过 c 将字符串作为指向它们的第一个字符的指针,直到它到达\\0但上面的代码不喜欢它,所以它让 ac 初学者感到困惑

First, let's give your two variables different names and contents, so we can clearly tell them apart.首先,让我们为您的两个变量指定不同的名称和内容,以便我们可以清楚地区分它们。

char *namep = "asd";
char name[] = "zxc";

These result in data structures which might look like this:这些导致数据结构可能如下所示:

       +-------+
namep: |   *   |
       +---|---+
           |
          /
         |
         V
       +---+---+---+----+
       | a | s | d | \0 |
       +---+---+---+----+

       +---+---+---+----+
namea: | z | x | c | \0 |
       +---+---+---+----+

Now let's look at your two printf calls:现在让我们看看你的两个printf调用:

printf("%p\n%p", (void *)&namep, (void *)&namep[0]);

Now, &namep gives you the address of the namep pointer.现在, &namep为您提供了namep指针的地址。
But &namep[0] gives you the address of the first character in the pointed-to string ( a ).但是&namep[0]为您提供了指向字符串 ( a ) 中第一个字符的地址。 If you had printed如果你已经打印

printf("%p\n", (void *)namep);

you would have seen the same thing.你会看到同样的事情。

printf("%p\n%p", (void *)&namea, (void *)&namea[0]);

Here, &namea gives you the address of the array.在这里, &namea为您提供数组的地址。
And &namea[0] gives you the address of its first character ( z ) — which is the same place. &namea[0]给你它的第一个字符 ( z ) 的地址——这是同一个地方。 And in fact, due to the special handling (the "decay" of arrays into pointers), if you had said事实上,由于特殊处理(数组“衰减”为指针),如果你说过

printf("%p\n", (void *)namea);

you would also have seen the same thing.你也会看到同样的事情。

You asked:你问:

i've read that c takes strings as a pointer to their first char, till it reaches the \\0我读过 c 将字符串作为指向它们第一个字符的指针,直到它到达 \\0

That's correct.没错。

Suppose you wrote the code假设你写了代码

char *p;
for(p = namep; *p != '\0'; p++)
    putchar(*p);

This would print your namep string, asd .这将打印您的namep字符串asd There's no mystery here.这里没有什么神秘之处。 namep was already a pointer, pointing at the first character of the string, so this scrap of code takes its own pointer p , which starts pointing where namep points, and prints the pointed-to characters until it gets to the terminating \\0 . namep已经是一个指针,指向字符串的第一个字符,所以这段代码采用自己的指针p ,它开始指向namep指向的位置,并打印指向的字符,直到它到达终止\\0

What's perhaps more surprising is that you can do exactly the same thing with namea :也许更令人惊讶的是,您可以使用namea完全相同的事情:

char *p;
for(p = namea; *p != '\0'; p++)
    putchar(*p);

This works, too, printing zxc , and if you don't believe me, I encourage you to type it into your C compiler and try it.这也可以打印zxc ,如果您不相信我,我鼓励您将它输入到您的 C 编译器中并尝试一下。

Now, you may be asking, if p is a pointer and namea is an array, how can the loop initialization p = namea work?现在,您可能会问,如果p是一个指针而namea是一个数组,那么循环初始化p = namea是如何工作的? And this, again, is due to the "decay" of arrays to pointers.这又是由于指向指针的数组的“衰减”。 Again, when you try to use namea 's value like this, what you get — the value that gets assigned to p — is automatically a pointer to namea 's first element.同样,当你尝试像这样使用namea的值时,你得到的——分配给p的值——自动是一个指向namea的第一个元素的指针。 And of course that's just what you want.当然,这正是您想要的。 p starts there, and prints characters 'til it finds a \\0 , thus printing zxc . p从那里开始,并打印字符 ' 直到找到\\0 ,从而打印zxc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM