[英]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.