【问题标题】:Why does printing the first element of a pointer to pointer to a char print the contents of a string?为什么打印指向 char 指针的指针的第一个元素会打印字符串的内容?
【发布时间】:2021-03-27 09:16:41
【问题描述】:

示例代码

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只是一个指向数组第一个元素的常量指针)。

【问题讨论】:

  • a[b] 只是*(a+b) 的语法糖,所以p[0]*(p+0) 或只是*p,而&p[0]&*p 就是p

标签: arrays c pointers dereference


【解决方案1】:

对于任何指针或数组p 和索引i,表达式p[i]完全等于*(p + i)

如果i == 0 那么我们有p[0] 等于*(p + 0) 又等于*(p) 等于*p

在您的情况下,*ps 相同。

【讨论】:

  • 感谢这位简短而明确的回答!今天打破了我的头......现在很高兴知道:)
【解决方案2】:

让我们从变量如何相互关联的图表开始:

   char **       char *     char
   +---+         +---+      +---+---+---+---+
p: |   |----> s: |   |----> |'k'|'u'|'t'| 0 |
   +---+         +---+      +---+---+---+---+

p 存储了s 的地址,s 存储了字符串文字"kut" 中第一个字符的地址,该地址作为char 的数组存储在内存中的某处。

鉴于此,以下关系均成立:

  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 

【讨论】:

    【解决方案3】:

    &p[0](p[0] 的地址)怎么会打印出 字符串 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
    

    【讨论】:

    • Re “对于初学者来说,你错了。这条语句printf("&amp;p[0]: %p\n", &amp;p[0]);输出的是指针s的地址”:它确实打印了s的地址,但是OP没有看错。他们说输出显示p[0]的地址(因此&amp;p[0])与p相同,这是真的;打印&amp;p[0]p 的输出相同。因为p指向s,所以p[0]就是s&amp;p[0]就是&amp;s,也就是p的值。
    • @EricPostpischil 他写道:“&p[0](p[0] 的地址)怎么会打印出字符串 kut?”
    【解决方案4】:

    printf("%s", p[0]) 表示您要打印从位置 p[0] 或 (*p) 开始并在到达 \0 字符时结束的字符串。

    【讨论】:

      猜你喜欢
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      相关资源
      最近更新 更多