【问题标题】:How do I use char** ? (pointer to an array of chars)如何使用 char** ? (指向字符数组的指针)
【发布时间】:2019-04-12 21:13:24
【问题描述】:

所以我正在尝试制作char**,我完全理解它在后台的工作原理以及所有这些东西,但我似乎不明白如何为其编写代码。我想创建一个指向其中有名称的字符数组的指针。我需要帮助在其中存储一个字符串(使用 strcpy() )并在此之后打印它。

char** name = (char**)malloc((strlen("MyName") + 1) * sizeof(char*));
strcpy(name, "MyName"); // I get an error right here

【问题讨论】:

  • 只需使用一个*。使用两个*,您正在声明一个指针数组,该数组可用于字符串数组。顺便说一句,如果您实际上是在编写 C 代码,don't cast the results of malloc。 C++ 是一种不同的语言,适用的规则也不同。
  • @user3386109;有两个*s,他不是声明一个指针数组,而是声明一个指向char数据类型的指针。
  • 当你收到错误时,第一步是阅读错误信息。
  • @hacks 这是一个没有区别的区别,因为指向单个 char 的指针与指向 char 数组的指针无法区分。
  • @user3386109;指向char 的指针、指向char 数组的指针和指向char 的指针数组都是不同的数据类型。三者互不兼容。

标签: c arrays pointers char


【解决方案1】:

如果你真的想要一个指向 char 数组的指针,你可以这样做:

char** name = (char**)malloc(sizeof(char*)); //initialize the pointer
*name = (char*)malloc((strlen("MyName") + 1) * sizeof(char)); //initialize the array
strcpy(*name, "MyName");

【讨论】:

  • strlen("MyName") + 1 == sizeof("MyName");字符串字面量的strlen没有太大意义
【解决方案2】:

所以我正在尝试制作char**,我完全理解它在 背景和所有这些东西,但我似乎不明白如何 为它写代码。

嗯...不,不完全是。

要声明一个 pointer-to-char,您只需 decalre:

    char *name = malloc (strlen("MyName") + 1);

为什么?当您调用malloc 时,malloc 分配一个内存块,提供strlen("MyName") + 1 字节并将起始地址返回到该内存块——您分配给name。然后,您可以将"MyName" 复制到名称(nul-terminating 字符剩余 1 个字节)。方法是:

    size_t len = strlen ("MyName");
    char *name = malloc (len + 1);      /* allocate len + 1 bytes */
    if (name == NULL) {                 /* validate EVERY allocation */
        perror ("malloc-name");
        /* handle error by returning or exiting */
    }
    memcpy (name, "MyName", len + 1);   /* no need to scan again for \0 */

    /* do something with name - here */

    free (name);    /* don't forget to free name when you are done */

那么char** 做了什么?

当你在处理一个pointer-to-pointer-to-char时,你必须先分配一些pointers,然后你才能分配和分配一个每个指针的内存块并使用每个指针,就像您在上面使用的name 一样。

例如:

    /* array of ponters to string-literals for your source of strings */
    char *band[] = { "George", "Ringo", "Paul", "John" };
    char **names;
    size_t nmembers = sizeof band / sizeof *band;

    /* allocate nmembers pointers */
    names = malloc (nmembers * sizeof *names);
    if (names == NULL) {                /* validate EVERY allocation */
        perror ("malloc-name_pointers");
        /* handle error by returning or exiting */
    }

    /* now loop allocating for each name and copy */
    for (size_t i = 0; i < nmembers; i++) {
        size_t len = strlen (band[i]);      /* get length */
        names[i] = malloc (len + 1);        /* allocate */
        if (names[i] == NULL) {             /* validate EVERY allocation */
            perror ("malloc-names[i]");
            /* handle error by returning or exiting */
        }
        memcpy (names[i], band[i], len + 1);/* no need to scan again for \0 */
    }

    /* output each */
    for (size_t i = 0; i < nmembers; i++)
        printf ("member[%zu]: %s\n", i + 1, names[i]);

释放names 是一个两步过程。您必须释放分配给每个 names 指针的内存,然后释放指针本身,例如

    for (size_t i = 0; i < nmembers; i++)
        free (names[i]);    /* free each allocated names[i] */
    free (names);           /* free pointers */

现在希望你更紧密地"... fully understand how it works"。如果您有任何问题,请告诉我。

【讨论】:

    【解决方案3】:

    首先您应该了解的是,将变量声明为单指针或双指针(或任何其他 n 指针)实际上并不能说明底层变量是保存单个值还是值数组。

    单指针指向存储实际值的内存地址。双指针指向存储单指针的内存地址,以此类推。

    现在,要创建指向 char 指针数组的指针,您可以使用单个 char 指针 (char*),但出于可维护性目的,我建议使用双 char 指针 (char**)。

    考虑以下代码:

    char** names = (char**)malloc(100 * sizeof(char*));
    

    它将为堆上的 100 个字符指针 (char*) 分配内存空间,并将双指针 (char**) 返回到该内存空间中的第一个单指针 (char*)。这意味着您将能够在该内存空间内保存 100 个字符指针(或在您的情况下为 100 个名称)。然后你可以像这样使用它们:

    char* name0 = "First Name"; // Saved on stack
    char* name1 = malloc((strlen("Second Name") + 1) * sizeof(char));  // Saved on heap
    strcpy(name1, "Second Name");
    
    names[0] = name0;
    names[1] = name1;
    

    另外,请注意,在堆上保存字符串时,您需要再添加一个空字符位置(手动)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-05
      • 2021-01-26
      • 2021-07-28
      • 2016-01-27
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多