为什么打印指向 char 的指针的指针的第一个元素会打印字符串的内容?
Why does printing the first element of a pointer to pointer to a char print the contents of a string?
示例代码
int main() {
char *s = "kut";
char **p = &s;
printf("*s: %c\n", *s);
printf("s: %p\n", s);
printf("&s[0]: %p\n", &s[0]);
printf("p: %p\n", p);
printf("*p: %p\n", *p);
printf("**p: %c\n", **p);
printf("p[0]: %s\n", p[0]);
printf("&p[0]: %p\n", &p[0]);
return 0;
}
输出:
*s: k
s: 0x1043acf46
&s[0]: 0x1043acf46
p: 0x7ffeeb853670
*p: 0x1043acf46
**p: k
p[0]: kut
&p[0]: 0x7ffeeb853670
&p[0]
(p[0]
的地址)怎么会打印出字符串kut
?输出显示 p[0]
的地址与 p
相同(因为 p
只是指向数组第一个元素的常量指针)。
对于任何指针或数组 p
和索引 i
,表达式 p[i]
正好 等于 *(p + i)
。
如果 i == 0
那么我们有 p[0]
等于 *(p + 0)
又等于 *(p)
与 *p
相同。
在您的情况下 *p
与 s
相同。
printf("%s", p[0])
表示您要打印从位置 p[0] 或 (*p) 开始并在到达 [=11=]
字符时结束的字符串。
让我们从变量之间如何相互关联的图表开始:
char ** char * char
+---+ +---+ +---+---+---+---+
p: | |----> s: | |----> |'k'|'u'|'t'| 0 |
+---+ +---+ +---+---+---+---+
p
存储s
的地址,s
存储字符串字面量"kut"
中第一个字符的地址,存储为[的数组=19=] 内存中某处。
鉴于此,以下关系都是正确的:
p == &s
*p == s == &"kut"[0] // believe it or not, this is legal - you
**p == *s == "kut"[0] == 'k' // can index into a string literal
鉴于a[i]
定义为*(a + i)
,这也意味着
*p == *(p + 0) == p[0] == s
和
&p[0] == &(*(p + 0)) == &(*p) == p;
和
*p[0] == *(*(p + 0)) == *(*p) == **p
How does it come that &p[0] (address of p[0]) does print out the
string kut?
首先你错了。这个说法
printf("&p[0]: %p\n", &p[0]);
输出指针的地址s
&p[0]: 0x7ffeeb853670
看来你指的是这个调用的输出
printf("p[0]: %s\n", p[0]);
确实在控制台上显示了字符串文字
p[0]: kut
函数 printf
中使用的转换说明符 %s
需要指向字符串第一个字符的指针。
例如printf的这个调用
printf("s: %p\n", s);
输出整个字符串文字 "kut"
.
指针p
声明为
char **p = &s;
并指向指针s
。
因此取消对指针的引用,如 p[0]
或 *p
(相同)会产生指针的值 s
。即 p[0]
等于 s
。所以这个调用
printf("p[0]: %s\n", p[0]);
与此调用效果相同
printf("s: %p\n", s);
因为调用的秒参数具有相同的类型和值。
这是一个演示程序。
#include <stdio.h>
int main(void)
{
char *s = "kut";
char **p = &s;
printf( "p[0] == s is %s\n", p[0] == s ? "true" : "false" );
return 0;
}
它的输出是
p[0] == s is true
示例代码
int main() {
char *s = "kut";
char **p = &s;
printf("*s: %c\n", *s);
printf("s: %p\n", s);
printf("&s[0]: %p\n", &s[0]);
printf("p: %p\n", p);
printf("*p: %p\n", *p);
printf("**p: %c\n", **p);
printf("p[0]: %s\n", p[0]);
printf("&p[0]: %p\n", &p[0]);
return 0;
}
输出:
*s: k
s: 0x1043acf46
&s[0]: 0x1043acf46
p: 0x7ffeeb853670
*p: 0x1043acf46
**p: k
p[0]: kut
&p[0]: 0x7ffeeb853670
&p[0]
(p[0]
的地址)怎么会打印出字符串kut
?输出显示 p[0]
的地址与 p
相同(因为 p
只是指向数组第一个元素的常量指针)。
对于任何指针或数组 p
和索引 i
,表达式 p[i]
正好 等于 *(p + i)
。
如果 i == 0
那么我们有 p[0]
等于 *(p + 0)
又等于 *(p)
与 *p
相同。
在您的情况下 *p
与 s
相同。
printf("%s", p[0])
表示您要打印从位置 p[0] 或 (*p) 开始并在到达 [=11=]
字符时结束的字符串。
让我们从变量之间如何相互关联的图表开始:
char ** char * char
+---+ +---+ +---+---+---+---+
p: | |----> s: | |----> |'k'|'u'|'t'| 0 |
+---+ +---+ +---+---+---+---+
p
存储s
的地址,s
存储字符串字面量"kut"
中第一个字符的地址,存储为[的数组=19=] 内存中某处。
鉴于此,以下关系都是正确的:
p == &s
*p == s == &"kut"[0] // believe it or not, this is legal - you
**p == *s == "kut"[0] == 'k' // can index into a string literal
鉴于a[i]
定义为*(a + i)
,这也意味着
*p == *(p + 0) == p[0] == s
和
&p[0] == &(*(p + 0)) == &(*p) == p;
和
*p[0] == *(*(p + 0)) == *(*p) == **p
How does it come that &p[0] (address of p[0]) does print out the string kut?
首先你错了。这个说法
printf("&p[0]: %p\n", &p[0]);
输出指针的地址s
&p[0]: 0x7ffeeb853670
看来你指的是这个调用的输出
printf("p[0]: %s\n", p[0]);
确实在控制台上显示了字符串文字
p[0]: kut
函数 printf
中使用的转换说明符 %s
需要指向字符串第一个字符的指针。
例如printf的这个调用
printf("s: %p\n", s);
输出整个字符串文字 "kut"
.
指针p
声明为
char **p = &s;
并指向指针s
。
因此取消对指针的引用,如 p[0]
或 *p
(相同)会产生指针的值 s
。即 p[0]
等于 s
。所以这个调用
printf("p[0]: %s\n", p[0]);
与此调用效果相同
printf("s: %p\n", s);
因为调用的秒参数具有相同的类型和值。
这是一个演示程序。
#include <stdio.h>
int main(void)
{
char *s = "kut";
char **p = &s;
printf( "p[0] == s is %s\n", p[0] == s ? "true" : "false" );
return 0;
}
它的输出是
p[0] == s is true