【问题标题】:Can I create an Array of Char pointers in C?我可以在 C 中创建一个 Char 指针数组吗?
【发布时间】:2012-03-10 06:53:58
【问题描述】:

我是 C 的新手,C 中的东西与我学过的任何其他语言都不同。在我的作业中,我想创建一个指向一个字符数组的字符数组,但不是创建一个多维字符数组,我想我会有更多的控制权并创建字符数组并将每个单独的字符放入索引中原始字符数组:

char keywords[10];
keywords[0] = "float";

上面的例子是为了澄清和简单的案例。但我的问题是由于我一直在做的研究,我对某些事情感到困惑。通常这适用于其他语言,但在 C 语言中是这样的:

char *keyword[10];
keywords[0] = "float";

但是当我想通过函数发送它时,为什么需要这样做:

void function(char **keyword); //function prototype

仅仅传递数组指针还不够吗?

【问题讨论】:

  • 你认为/期望函数原型应该是什么?
  • 你也可以传递char *keyword[],意思完全一样
  • 是的,你可以....做你想做的事。但真正的问题是你读过哪些好的 C 编程书籍......
  • 嗯,这就是我要问的,我在别人的问题中看到了这个,但是两颗星**令人困惑。
  • 我没有读过书,只是在网上研究。在课堂上,教授把我们扔到公共汽车下,让我们学习不同的语言。我来自java、php背景。

标签: c arrays multidimensional-array


【解决方案1】:

你好像被里面的双星弄糊涂了

void function(char ** keyword);

双星只是意味着这个函数希望你传递一个指向一个char的指针。此语法不包含有关您正在使用数组这一事实的任何信息,或者 char 实际上是字符串中许多字符的第一个 char。作为程序员,您需要知道char ** 实际指向的是哪种数据结构。

例如,假设您的数组的开头存储在地址 0x1000。函数的 keyword 参数的值应为 0x1000。如果取消引用keyword,则会得到数组中的第一个条目,即指向字符串“float”中第一个字符的char *。如果你取消引用char *,你会得到字符“f”。

(人为的)代码如下所示:

void function(char **keyword)
{
    char * first_string = *keyword;   // *keyword is equivalent to keyword[0]
    char first_char = *first_string;  // *first_string is equivalent to first_string[0]
}

上面的例子中有两个指针。通过在取消引用之前向第一个指针添加偏移量,您可以访问数组中的不同字符串。通过在取消引用之前向第二个指针添加偏移量,您可以访问字符串中的不同字符。

【讨论】:

  • 我明白你在说什么。它与星星有点混淆,但我感谢您的澄清。
  • 为类型 T 添加星号只是将其更改为“指向 T 的指针”。所以“char *”是“指向char的指针”,“char **”是“指向char的指针”。
【解决方案2】:

我假设你正在分配你的第一个字符串:

"float"

到关键字[0]的第一个索引位置

char keyword[0] = "float";

这是数组的第一个索引位置:

char keyword[10];

如果是前面的情况,那么从某种意义上说,您本质上是在创建一个包含数据结构的数据结构。任何类型的数组都是 C 中该类型的“最小”数据结构。考虑到在您的示例中您正在创建一个字符数组,那么您实际上是在每个索引位置使用最小的数据类型(char=1bit)最小的内置数据结构(数组)。

话虽如此,如果在您的示例中,您正在尝试创建一个数组数组;你的字符数组

/* Hold ten characters total */
char keyword[10];  

旨在容纳 10 个字符。每个索引位置一个(您可能已经知道)。因此,在声明数组 titled 关键字后,您尝试用另一个(第二个)字符数组初始化数组的第一个索引位置:

/* I believe this is what you had stated */
char keywords[0] = "float";

第二个字符数组的索引大小为 5 个位置。

为了实现您想要的目标,您实际上将创建一个数组,该数组基本上模拟“保存”其他数据结构的数据结构的效果。

注意:如果您有/有计划尝试创建一个包含数据结构的数据结构。又名一个三重嵌套的数据结构,在这种情况下,我认为这将是一个矩阵,我不建议这样做!

尽管如此,矩阵结构将是关键字的第一个索引位置的形式,被分配了整个关键字数组,其中包括存储在关键字数组的每个索引位置的所有数据。然后可能会有类似:keywords1,keywords2,...keywords9,

本质上会模仿以下形式:

char *keyword[10] = { 
                        char *keywords0[10] = {"float", etc, etc, etc.};
                        char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.}; 
                       and so

                   };

所以基本上从右到左,关键字数组,是一个指针数组,指向指向字符数组的指针数组。

如果这就是您所代表的,您最好定义一个自定义数据类型的结构/记录,并且在该自定义结构中,您需要定义一个从属或子级别的结构。你也可以预先声明它们然后初始化它们。

例如

typedef *nestedDataStructures {

    struct keyWords[];
    struct keyWords1[];
    struct keyWords2[];

    ... and so on.
}; nestedDataStructures

我不会将十个结构添加到一个自定义结构中,而是分解为 3 或 4 个(多少结构和使用多少)并创建一个模块,以便在您操作数据集时产生对称的抽象层。

尽管如此,您不能创建字符数组并可能以您所做的方式(或者谁知道也许您可以)分配另一个字符数组,但是您希望模拟包含数组的数组的方式,是先创建一个字符指针数组,X个索引位置,然后初始化,然后使用在原始声明的初始化中声明的字符串形式的字符数组。

所以基本上你可以预先声明你的整个数组,然后在你的程序设计中,或者取消引用每个索引位置,使用赋值,或者打印/写入索引位置。

例如,您总是可以这样做:

/* Example of the program and declaration with out a function */
#include <stdio.h>

int main(){

    /* 
     * A character pointer array that contains multiple 
     * character arrays.
     */

    char *grewMe[2] = {"I want to ", "grow to be bigger"};

    int w = 0;

    for(; w < 2;) {
        printf("%s", grewMe[w]);
        ++w;
    }

    printf(" :-)\n");
    w = 0;
    return 0;
}
// Output:
// I want to grow to be bigger :-)

或者是这样的:

/* Example of program: function passed arguments 
 * of a pointer to the array of pointers 
 */
#include <stdio.h>

void mygrowth(char *growMe[]);

int main(){

    char *growMe[2] = {"I want to ", "grow to be bigger"};

    mygrowth(growMe);  
    printf(" :-)\n");

    return 0;

}
void mygrowth(char *growMe[])
{

    int w = 0;
    for (; w < 2;) {
        printf("%s", growMe[w]);
        ++w;
    } 
}

作为参数传递的每个索引位置的分配:

/* 
 * This program compiles, runs and outputs properly
 * Example of a program with a function of 
 * arguments pnt2pnter 
 */

#include <stdio.h>
#include <stdlib.h>

void thoughtAsAFunction(char **iThink);

int main()
{

    char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
                        "accomplish. My father is short ", 
                        "my mother is even shorter than him, ", 
                        "what is the probability of me getting taller? ", 
                        "Well both my grandfather's were Six ",
                        "Foot Five, and both my grandmother's ", 
                        "were over 5 foot 8 inches tall! If my ",  
                        "grandparent's genes point to my parents, and my ", 
                        "parent's genes point to mine I might have a chance ",
                        "of being 6 foot. Do you know what I mean? "};

    thoughtAsAFunction(iThink);

    printf(":-)\n");

    return 0;
}
void thoughtAsAFunction(char **iThink) {

    int andy = 0;
    for (; andy < 10;) {
        char * pntThroughPnt = iThink[andy];
        printf("%s", pntThroughPnt);
        ++andy;
    }
    andy = 0;
}

或者通过引用传递,增加循环计数变量:

/*
 * This program compiles, runs, and outputs all of the character
 * arrays. 
 * 
 */
#include <stdio.h>
#include <stdlib.h>

void thoughtAsAFunction(char **iThink);

int main()
{

    char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
                        "accomplish. My father is short ", 
                        "my mother is even shorter than him, ", 
                        "what is the probability of me getting taller? ", 
                        "Well both my grandfather's were Six ",
                        "Foot Five, and both my grandmother's ", 
                        "were over 5 foot 8 inches tall! If my ",  
                        "grandparent's genes point to my parents, and my ", 
                        "parent's genes point to mine, then I might have a chance ",
                        "of being 6 foot. Do you know what I mean? "};

    int andy = 0;
    for (; andy < 10;) {
        // pass by reference and increment.
        thoughtAsAFunction(&iThink[andy]);
        ++andy;

    }

    printf(":-)\n");
    andy = 0;

    return 0;
}
void thoughtAsAFunction(char **iThink) {

    char * pntThroughPnt = *iThink;
    printf("%s", pntThroughPnt);

}

请记住,如果您声明了指针数组 (char *array[10];),并且每个指针都指向一个字符数组,就会出现这种情况。

【讨论】:

    【解决方案3】:

    这就是答案。

    #include<stdio.h>
    
    int main(void)
    {
            char *CharPtr[3];
            char a[4]="abc";
            char b[4]="def";
            char c[4]="ghi";
            CharPtr[0]=a;
            CharPtr[1]=b;
            CharPtr[2]=c;
    
            printf("\n content of CharPtr[0] =%s",CharPtr[0]);
            printf("\n content of CharPtr[1] =%s",CharPtr[1]);
            printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
    
            printf(" \n content of char a[4]=%s",a);
            printf(" \n content of char b[4]=%s",b);
            printf(" \n content of char c[4]=%s\n",c);
    }
    

    【讨论】:

    • 这与问题中所问的不完全一样...我认为您应该先仔细阅读问题...
    【解决方案4】:

    char *keywords[10] 是一个字符指针数组。所以keywords[0]keywords[1]..等等会有不同字符数组的地址。

    printf 中,您可以使用%skeywords[0] 打印其地址(即数组中第一个字节的地址)存储在keywords[0] 的整个字符数组。

    在传递给函数时,如果您提供*keywords,您指的是值at(存储在keywords[0])的值,这又是一个地址。因此,要获取值而不是地址,您可以添加另一个 *... 希望澄清一点..

    【讨论】:

      【解决方案5】:
      char *keyword[10];
      

      keywordchar * 的数组 10。在值上下文中,它转换为指向char * 的指针。

      这种转换是 Chris Torek 所说的“规则”的一部分:

      “正如在别处提到的,C 有一条关于数组和指针的非常重要的规则。这条规则——规则——说,在值上下文中,类型为“T 的数组”的对象变成了类型为“指向 T' 的指针,指向该数组的第一个元素"

      更多信息请看这里:http://web.torek.net/torek/c/pa.html

      C-FAQ 也有一个关于这个数组到指针转换的条目:

      问题 6.3:那么 C 中的“指针和数组等价”是什么意思?

      http://c-faq.com/aryptr/aryptrequiv.html

      【讨论】:

      • 这是正确的,但对于刚接触该语言的人来说不是很清楚。您应该考虑解释“价值上下文”的含义。
      【解决方案6】:

      如果你愿意

      void function(char **keyword);
      

      安迪,想想数组只是一个指针(指向数组的开头),这就是你写的原因:

      void function(char **keyword);
      

      因为您已经创建了一个指向 char 指针的数组。

      如果更容易理解试试:

      void function(char *keyword[]);
      

      但使用第一个更符合 C 标准,不过如果您使用 C++ 编译器则无关紧要。

      【讨论】:

        【解决方案7】:

        在 C 中,您不能真正将数组传递给函数。相反,您将指针传递给数组的开头。由于您有char* 的数组,因此该函数将获得指向char* 的指针,即char**

        如果你愿意,你可以写(在原型中)char *keyword[] 而不是char **keyword。编译器会自动转换。

        此外,在 C 语言中,您可以像数组一样取消引用指针,因此“转换为指针”几乎不会丢失任何内容。

        【讨论】:

          猜你喜欢
          • 2021-10-17
          • 2020-06-05
          • 1970-01-01
          • 2017-06-19
          • 2020-12-31
          • 2013-08-24
          • 1970-01-01
          • 2021-01-26
          • 2021-05-28
          相关资源
          最近更新 更多