【问题标题】:Using Arrays of strings in function在函数中使用字符串数组
【发布时间】:2022-01-14 10:35:51
【问题描述】:

我正在练习字符串数组,但似乎我不明白它是如何工作的,有人可以向我解释一下什么是制定这段代码的正确方法吗?

代码目的:将 2 个字符串分配给一个字符串数组并使用函数打印它们。

错误: 编译器没有发现任何错误,但我根本没有在终端中得到任何输出。

#include <stdio.h>

#define MAX 100

void function(char **);

int main()
{    
    char *a[MAX]; /*array of max 100 strings*/
    a[0] = "test0";
    function(&a[MAX]);    
    return 0;
}

void function(char *a[MAX])
{    
    a[1] = "test1";
    printf("%s",*a[1]);
    printf("%s",*a[0]);
}

【问题讨论】:

  • 您的意思是在第一次打印时使用"%d"?怎么了?
  • 不,这是一个小错误,但不是主要问题,我更新了问题
  • 您的具体问题是什么? -- 在指针数组的最后一个元素之后将指针传递给函数。我确定这不是您想要的。
  • 您正在向函数传递a最后一个 元素的地址,这也是错误的类型。你应该在这里收到一堆警告。
  • 对不起,如果问题不够清楚,我的目的是打印 a[1] 和 a[0] 中的值,但我只是遇到了一些错误,我要走了编辑添加这些的问题。

标签: arrays c string pointers


【解决方案1】:

编译器没有发现任何错误,但我根本没有在终端中得到任何输出。

那是因为你传递的地址不是你的函数所期望的。

function(&a[MAX]);

您正在传递数组a 中索引MAX 处的项目地址,但您的函数将其解释为整个数组的地址。你应该写:

function(a)

您似乎混淆了参数的声明方式和函数调用中的使用方式。当你声明一个函数时,你必须指定参数的类型,所以你说例如char *s[] 表示指向字符的指针数组。但是当你调用一个函数时,编译器已经知道函数期望的类型,所以你只需要传递一个与声明类型匹配的变量。此上下文中的方括号,如a[MAX],被解释为选择数组的一个元素的下标。

旁白:就风格而言,function 是一个糟糕的函数名称。我知道这只是一个很小的测试程序,所以没什么大不了的,但要养成给事物起描述性名称的习惯。

还有:

printf("%s",*a[1]);
printf("%s",*a[0]);

在这里,您正在访问索引 1 处的项目,但您还没有在那里存储任何内容。这不是一个好计划。要么删除第一行,要么更改代码以将某些内容存储在索引 1 中。

此外,您不需要取消引用元素。数组中的每个元素都是一个字符数组,printf() 将期望char * 类型的值,这就是每个a[n] 的值。所以只需使用:

printf("%s", a[1]);
printf("%s", a[0]);

【讨论】:

  • 是否将数组称为 function(a) ,将整个数组数组赋予函数? p.s.我确实分配了 a[1],但我尝试在函数内部执行它以测试它是如何工作的。
  • 抱歉,错过了a[1]。无论如何,是的,将数组称为 a 提供了数组的值,它实际上只是第一个元素的地址(索引 0 处的那个)。出于同样的原因,您的 printf() 语句应将字符串引用为例如a[0],不是*a[0]*a[0] 是数组中第一个字符串的第一个字符。请注意我刚才的编辑添加了这一点。
  • 谢谢,这似乎有效!如果我想在函数中访问字符串 a[0] 的第三个字母怎么办?
  • 有更短的方法,但最好在学习时保持简单:char *s = a[0]; char c = s[2];
【解决方案2】:

你需要传递数组的指针,即

function(a)

【讨论】:

    【解决方案3】:

    您似乎对正在使用的指针及其正确类型有些困惑。希望下面的程序可以解决一些问题。 cmets中有解释:

    #include <stdio.h>
    
    #define MAX 100
    
    void function(char* (*aPtr)[MAX])
    {
        // Since aPtr is a pointer, we need to derefecence it with * before assigning
        // string literals
        (*aPtr)[1] = "test1";
        printf("In function\n");
        printf("%s\n",(*aPtr)[0]);
        printf("%s\n\n",(*aPtr)[1]);
    }
    
    void function2(char** a)
    {
        // Remember, * and [] can both be used to dereference in C
        // This is equivalent to *(a+2) = "test2";
        a[2] = "test2";
        printf("In function2\n");
        printf("%s\n",a[0]);
        printf("%s\n",a[1]);
        printf("%s\n\n",a[2]);
    }
    
    int main(void)
    {
        // This is an array of MAX char pointers. Just on declaration, each pointer in the array
        // points to nothing. You can point them to a string literal (as you have done), or use
        // something like malloc to allocate space for each one
        char *a[MAX];
        // This is a pointer to an array of MAX char pointers. This is the type you're trying to
        // pass to `function`, which is not used correctly
        char* (*aPtr)[MAX] = &a;
        // I've included these prints so you can see the difference between `a` and `aPtr` via pointer
        // arithmetic. In this printf, `a` "decays" to a pointer to the first element in the array.
        // The first element of the array is a `char*`, so a pointer to that is a `char**`, so
        // that's what `a` is in this context, pointing to a[0]. What the actual address is here isn't
        // important, just think of this as offset 0
        printf("pointer to first element      = %p\n", (void*)a);
        // This is the explicit address of the first element in the array. Notice how it is
        // identical to the address of the array above.
        printf("address of first element      = %p\n", ((void*)&(a[0])));
        // This illustrates the "decay" concept again. `a` decays to a `char**`, and +1 on that
        // shows pointer arithmetic. On this architecture, pointers are 8 bytes, so a+1
        // advances the pointer by 8 bytes, which points to the 2nd element in the array.
        // This output will be the offset +8
        printf("pointer to second element     = %p\n", (void*)(a+1));
        // This shows the address of aPtr. Remember, this is a pointer to an array of char
        // pointers 100 large. This base address is also the address of where the array starts,
        // so it will be identical to offset
        printf("address of array              = %p\n", (void*)aPtr);
        // This is where the different pointer types are illustrated. Since char pointers are 8
        // bytes on this architecture, an array of 100 of them is 8*100 = 800 bytes. So aPtr+1
        // here performs pointer arithmetic on that type, meaning it advances the pointer 800
        // bytes. The print out here will be offset +800.
        printf("pointer to next array element = %p\n\n", (void*)(aPtr+1));
    
        // assign a[0] to point to the string literal "test0"
        a[0] = "test0";
    
        // This is what you're trying to do (but doing incorrectly) with your function call.
        // This passes the address of `a`, a pointer to an array of char pointers 100 large.
        // This is identical to passing `&a`, the address of `a`.
        function(aPtr);
        // `a` in this context "decays" to a pointer to its first element. Its first element is
        // `char*`, so here `a` is `char**`. And this is the signature you'll find in function2
        function2(a);
    
        // print out in main to show all the assignments were made
        printf("in main\n");
        printf("%s\n",a[0]);
        printf("%s\n",a[1]);
        printf("%s\n",a[2]);
    
        return 0;
    }
    

    Demo

    【讨论】:

    • 哇!多么详细的答案,谢谢!我仍然有疑问,如果在函数 2 中我想要 a[0] 的第三个字母怎么办?
    • @Pinguiz 我总是需要考虑指向数组的指针,我和你一样清楚地说明了这一点。第一个字符串的第三个字母是a[0][2]。在function2 中,achar**,所以a[0] 是第一个char*a[0][2] 是第三个char 与第一个char* 的偏移量。您可以转到演示链接并在该沙盒中玩,不要忘记"%c" 是打印char 的格式说明符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-22
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多