C 数组到指针

C Array to Pointers

请解释为什么下面的代码在 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**,但应用程序冻结了。

您已经声明了一个字符数组并为其赋值。如果你只是提到数组的名称,实际上你是在提到这个数组的基地址。指针可以存储地址,你可以定义一个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);

如果这是你想要的

在 c 中 ar 等于 &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;
}
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;
}

我在你代码的注释里解释。

编辑:不要复制以下代码

#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;
}

How can I print values of p, i.e. Hello World.

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

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

这道题是数组和指针区别的一个有趣例子。人们通常将数组视为指针,但事实并非如此。 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;
}

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

虽然数组 衰减的上下文之一是在获取其地址时:地址运算符产生指向数组的指针,而不是指向 char 指针的指针:

char arr[6] = "abcde";  // 5 letters plus '[=10=]'
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 页

何时使用**指针的示例

#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;
}