3

我在这里做错了什么,将一个char数组传递给一个函数,并在函数中给出每个索引内存(使用malloc()),然后使用gets()从键盘插入一些东西。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

void test(char *arr[]);
int main(){
  char *arr[2];//2 is the rows
 /* arr[0] = malloc(80);//This commented code works
  arr[1] = malloc(80);
  strcpy(arr[0], "hey");
  strcpy(arr[1], "whats up");
*/

  test(*arr);
  printf("in array[0]: %s", arr[0]);
  printf("in array[1]: %s", arr[1]);
  return 0;
}
void test(char *arr[]){
  int index;
  char *input = malloc(80);
  for(index = 0; index < 2; index++){
  arr[index] = malloc(80);
  gets(input);
  strcpy(arr[index], input);
  //arr[0] = input;
  }
}

只是一个非常基本的程序,由于某种原因我遇到了麻烦。还有一个问题当我声明一个数组时,这些形式有什么区别

char *array

反对

char *array[size]

或者

char **array

谢谢,凯文

4

3 回答 3

3

您声明arrchar *arr[2]. 然后你传入*arr,它有char*要测试的类型。但是测试需要一个char *[]. 所以这行不通。您应该简单地按arr原样传入,即test(arr).

char * array是指向字符的指针,通常用于指向字符数组(即字符串)中的第一个字符。 char **array是指向字符的指针。通常用于表示字符串数组。 char *array[size]基本上等同于上面的那个,但它不像那个,顶层指针已经指向一个有效的数组,所以不需要malloc编辑数组。

顺便说一句,您的test功能可以简化一点:这strcopy是不必要的。

void test(char *arr[])
{
    int i;
    for(i=0;i<2;i++)
    {
        arr[i] = malloc(80);
        gets(arr[i]);
    }
}
于 2012-11-01T00:14:58.077 回答
1

好的,在 C 声明中,您只会获得从声明中读取的第一个分配的内容。

在您了解如何阅读声明之前,这有点晦涩难懂。

运算符具有优先级,并且该优先级适用于声明。为简单起见,取:

() - Either raises precedence, or means "function taking parameters and returning..."
[] - Array of
* - Pointer to (right associative)

所以,声明:

char *a[3];

是“3 个指向 char 的指针的数组”,而

char (*a)[3];

是“指向 3 字符数组的指针”(指向行宽为 3 的多维字符数组的行的指针)

编译器在堆栈上分配第一件事。因此,在第一个示例中,您获得了三个能够指向(尚未分配的)字符的指针。

| ptr | --> (unallocated char)
| ptr | --> (unalloc char)
| ptr | --> (unalloc char)

在第二:

| ptr | --> (unallocated block of 3 char)

下一条规则是:如果你有一个指针,你就有一个数组。所以在这两种情况下,你都会得到多维数组。

首先,行数是固定的(您已经分配了它),但是每一行可以有不同的大小,因为编译器知道指针可以偏移一个字符以到达下一个字符。

第二,你有一个固定的行大小,但编译器知道如何偏移你的基指针(每个 3 个字符),所以你有任意数量的行。

C 也是一种按值调用的语言。所以,如果你声明了一个变量:

char *a[3];

那么 'a' 本身就是“一个 3 ptr 到 char 的数组”,但 a[0] 是“一个 char 的 ptr”,而 a[0][0] 是一个 char。

当您编写一个期望的函数时:

void f(char *arg[]) {
...
}

您必须将一个指向 char 的指针数组传递给它。它不关心有多少行(你必须跟踪它)......它只关心类型是否正确。

因此,如果您像我们的第一个示例中那样声明了“a”,则必须调用 f(a)。函数调用对函数 args 执行类似赋值的操作:

f(a) 表示用 (arg = a) 调用 f。

优先规则特别重要,你应该研究这些,直到你能读到这样的声明:

int (*f(int (*a)[4], void (*f)()))[6];

which is "f is a function that takes:
  - a pointer to arrays of 4 int
  - a pointer to a function that takes nothing and returns nothing)
and (then f) returns a pointer to arrays of 6 int".
于 2012-11-01T00:17:49.153 回答
0

char *array 创建一个指向内存字节的指针。char *array[size] 创建一个指向长度为“size”的数组的指针。char **array 只是一个指向内存字节指针的指针

如您所见,您的代码的问题在于您试图通过测试功能它不期望的东西。测试函数想要一个指向指针的指针,你只需给它一个指针。正确的段落是:test(arr);

从第二个角度来看:您在制作命令行程序时会看到这一点(有点)。

考虑以下代码:

#include<stdio.h>

int main(int argc, char *argv[]) {
    printf("%s\n", argv[0]);
    return 0;
}

argv 指针指向命令行参数,每个参数都是一个字符串(它只是一个指针,或一个数组)。因此,假设您为 Linux 执行了以下操作:

./some_program -option 选择输入

这些中的每一个都被视为自己的字符串。char *argv[] 指向每个字符串。第一个 printf 将打印出 ./some_program,因为这是 argv 指向的第一个字符串。

于 2012-11-01T00:27:38.340 回答