【问题标题】:C Array to Pointers指向指针的 C 数组
【发布时间】:2016-09-17 15:48:09
【问题描述】:

请解释为什么下面的代码在line 10 处失败。 如何打印p 的值,即Hello World

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
    char ar[200] = "Hello World";
    strcat(ar, " !");
    printf("%s\n", ar);

    char **p = &ar;
    printf("%s\n", *p[0]);

    return 0;
}

编辑:

只是为了进一步说明我想要实现的目标。我有一个接受char** 作为参数的函数,因此我想将char ar[200] 转换为char**,但应用程序冻结了。

【问题讨论】:

  • 不应该是printf("%s\n", (*p)[0]);吗?
  • @RoshDonniet OP 想通过 p 打印整个字符串
  • printf("%s\n", p[0]);printf("%s\n", *p);。通过执行printf("%s\n", *p[0]);,指向字符串p 的指针被取消引用两次。因此,*p[0] 是一个字符,而不是一个字符串。
  • @RoshDonniet,我试过了,但程序最后崩溃了
  • &amp;ar 的类型是char (*)[200](指向char 的200 元素数组的指针),而不是char **

标签: c arrays pointers memory-address dereference


【解决方案1】:

我在你的代码中解释。

编辑:不要复制以下代码

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
    char ar[200] = "Hello World";// technically an array is a pointer, so char *ar and char[] are the same
    strcat(ar, " !");// pass the pointer to treat strings
    printf("%s\n", ar);// pass the pointer to treat strings

    char **p;// here is the problem you were giving the address of your pointer to a pointer of pointer in inline wich makes more confusing
    (*p) = &ar; // here is the correct assingment
    printf("%s\n", *p);// so here you should pass  *p
    return 0;
}

编辑:这种解决方案在现实生活中要安全得多

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
    char ar[200] = "Hello World";// technically an array is a pointer, so char *ar and char[] are the same
    strcat(ar, " !");// pass the pointer to treat strings
    printf("%s\n", ar);// pass the pointer to treat strings

    // This solution initializing is better because it avoids editing other variables
    char *p = ar;
    char **pp = &p;

    printf("%s\n", *pp);// so here you should pass  *pp
    return 0;
}

【讨论】:

  • (*p) = &amp;ar; 这将取消对未初始化的 p 的引用
  • 指针不需要初始化,因为它指向内存中的地址。这是正常工作的测试:(ideone.com/cnM9Jn#stdin)
  • gcc 抱怨:test95.c:10:10:警告:“p”在此函数中未初始化 [-Wuninitialized]
  • 你能说出ar&amp;ar之间的区别吗??
  • 我编写了一个概念验证程序,您的代码如何覆盖程序中的另一个变量。参照。 coliru.stacked-crooked.com/a/2a9c14e9bae022ac。这种错误很难发现。
【解决方案2】:

在大多数情况下,数组已经“衰减”到其第一个元素的地址。这种行为不同于其他变量,甚至不同于其他聚合、结构。原因深深植根于 C 的历史中(即,不开玩笑,在 B1 中)。

虽然数组衰减的情况之一是它的地址被取走:地址运算符产生一个指向数组的指针,而不是指向char的指针:

char arr[6] = "abcde";  // 5 letters plus '\0'
char (*parr)[6] = &arr; // pointer to array of 6 elements

奇怪的是,两次取消引用此指针会产生数组中的第一个字符,就好像parr 指向字符指针的指针。原因是 *parr 只是原始数组,而取消引用 that 通常是它的第一个元素。这可能是很多混乱的根源:

printf("%c", **parr);

传统上(即 1970 年代)指针是指针,它们的类型并不重要。 (但有一个很大的区别:parr+1 有什么价值?)但是很高兴在没有警告的情况下编译并了解一个人在做什么。那么,我们如何获得您的要求,一个指向字符指针的指针,用于打印arr?答案是,只需使用指向指针的指针!

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
    char ar[200] = "Hello World";
    strcat(ar, " !");
    printf("%s\n", ar);

    char *p = ar;  // pointer to char: 
                   // array "decays" to address of first char

    char **pp = &p;  // pp is a pointer to a pointer to char.
                     // The point is, it points to the "pointer to char" p.

    printf("%s\n", *pp); // *pp is what pp points to: 
                         // p, a simple pointer to char. That's what "%s"
                         // expects. p is initialized and points to 
                         // the first char in ar.

    return 0;
}


1参见。 Dennis Ritchie 的有趣论文,"The Development of the C Language",第 7 页

【讨论】:

    【解决方案3】:

    这个问题是一个有趣的例子,说明了数组和指针之间的区别。通常将数组视为指针,但这并不完全正确。 char ar[200] ar 变成字符指针这一事实就是为什么你不能使用char** 指向ar。另一方面,数组在函数调用中衰减为指针,所以下面的代码确实可以工作(尽管它非常缺乏动力):

    #include <stdio.h>
    #include <string.h>
    
    void printString(char ar[]){
        char **p = &ar; // as in original code
        printf("%s\n",*p);
    }
    
    int main(int argc, char **argv) {
        char ar[200] = "Hello World";
        strcat(ar, " !");
        printf("%s\n", ar);
    
        printString(ar); 
    
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      何时使用**指针的示例

      #include <stdio.h>
      
      void foo(char **bar)
      {
        *bar = "some text";
      }
      
      int main(int argc, char *argv[])
      {
        char *temp;
      
        foo (&temp);
      
        printf ("temp=%s\n", temp);
      
        return 0;
      }
      

      【讨论】:

        【解决方案5】:

        在c中ar等于&amp;ar,因为数组基本上是它们第一个元素的内存地址。
        所以你只需要一个指向 char 的指针,而不是指向 char 的指针。

        #include <stdio.h>
        #include <string.h>
        
        int main(int argc, char **argv) {
            char ar[200] = "Hello World";
            strcat(ar, " !");
            printf("%s\n", ar);
        
            char *p = &ar;
            printf("%s\n", p);
        
            return 0;
        }
        

        【讨论】:

          【解决方案6】:

          您已经声明了一个字符数组并为其赋值。如果你只是提到数组的名称,你实际上是在提到这个数组的基地址。指针可以存储地址,你可以定义一个char指针并将你的字符数组的基地址分配给它。

          例如

          char ar[200]="Hello World";
          char *p=a; //assign the base address of a to p;
          

          然后您可以使用 %s 格式说明符和您的字符数组(字符串)的基地址来打印字符串。

          printf("%s",a);// print the string "Hello World". here a is the base address
          printf("%s",p);//print the string "Hello World". here p is the base address
          

          这会起作用

          #include <stdio.h>
          #include <string.h>
          int main(int argc, char **argv) {
              char ar[200] = "Hello World";
              strcat(ar, " !");
              printf("%s\n", ar);
              char *p = ar;
              printf("%s\n", p);
              return 0;
          }
          

          为方便起见编辑

          char *q=a;
          char **P=&q;
          printf("%s",*p);
          

          如果这是你想要的

          【讨论】:

          • 你应该解释为什么它可以工作而他的代码没有
          • @JohnColeman 我很欣赏你的世界,非常感谢他
          【解决方案7】:
          gcc     main.c   -o main
          main.c: In function ‘main’:
          main.c:9:16: warning: initialization from incompatible pointer type [enabled by default]
               char **p = &ar;
                          ^
          main.c:10:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
               printf("%s\n", *p[0]);
               ^
          

          expects argument of type ‘char *’, but argument 2 has type ‘int’ 看起来很清楚:P

          你可以通过改变你的程序来打印你的字符串

          int main(int argc, char **argv) {
              char ar[200] = "Hello World";
              strcat(ar, " !");
          
              char *p = ar;
              printf("%s\n", p);
          
              return 0;
          }
          

          【讨论】:

            【解决方案8】:

            如何打印 p 的值,即 Hello World。

            为此,您不需要指向指针的指针。一个简单的指针就可以了。

            char *p;
            p = ar;
            printf ("%s\n",p);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-08-25
              • 2013-04-19
              • 2023-03-11
              • 2010-10-25
              • 1970-01-01
              • 2012-05-02
              相关资源
              最近更新 更多