在函数中使用字符串数组
Posted
技术标签:
【中文标题】在函数中使用字符串数组【英文标题】: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] 中的值,但我只是遇到了一些错误,我要走了编辑添加这些的问题。
【参考方案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
中,a
是char**
,所以a[0]
是第一个char*
,a[0][2]
是第三个char
与第一个char*
的偏移量。您可以转到演示链接并在该沙盒中玩,不要忘记"%c"
是打印char
的格式说明符。以上是关于在函数中使用字符串数组的主要内容,如果未能解决你的问题,请参考以下文章