为什么函数(char*array[])是有效的函数定义,而不是C中的(char(*array)[])?

为什么函数(char*array[])是有效的函数定义,而不是C中的(char(*array)[])?,c,C,我认为这是因为前者是指向char的指针数组,而后者是指向char数组的指针,我们需要为函数定义正确指定指向的对象的大小 function(char * p_array[]) 指向的对象的大小已经包括在内(它是指向char的指针),但是后者 function(char (*p_array)[]) 需要将数组p_数组点的大小作为p_数组定义的一部分吗? 我现在正处于思考这个问题太久的阶段,我只是把自己弄糊涂了,请有人告诉我我的推理是否正确。因为 (1) function(char * p_arr

我认为这是因为前者是指向char的指针数组,而后者是指向char数组的指针,我们需要为函数定义正确指定指向的对象的大小

function(char * p_array[])
指向的对象的大小已经包括在内(它是指向char的指针),但是后者

function(char (*p_array)[])
需要将数组p_数组点的大小作为p_数组定义的一部分吗? 我现在正处于思考这个问题太久的阶段,我只是把自己弄糊涂了,请有人告诉我我的推理是否正确。

因为

(1) function(char * p_array[])
相当于
char**p_数组
;即有效的双指针

(2) function(char (*p_array)[])

您是对的,
p\u array
是指向
char
array的指针。但是当它显示为函数参数时,需要具有固定的大小。您需要提供大小,并且该大小也将变为有效。

在C中都是有效的,但不是C++。您通常是正确的:

char *x[]; // array of pointers to char
char (*y)[]; // pointer to array of char
但是,如果数组显示为函数参数,则会衰减为指针。因此,它们变成:

char **x; // Changes to pointer to array of pointer to char
char (*y)[]; // No decay, since it's NOT an array, it's a pointer to an array
在C中的数组类型中,允许未指定其中一个大小。这必须是最左边的一个(哎呀,我一开始说的是最右边的)。所以

(你可以把它们锁起来……但我们很少有理由这么做……)

有一个问题,问题是,其中包含
[]
的数组类型是不完整的类型。您可以传递指向不完整类型的指针,但某些操作不起作用,因为它们需要完整的类型。例如,这不起作用:

void func(int (*x)[])
{
    x[2][5] = 900; // Error
}
这是一个错误,因为为了找到
x[2]
的地址,编译器需要知道
x[0]
x[1]
有多大。但是
x[0]
x[1]
有类型
int[]
,这是一个不完整的类型,没有关于它有多大的信息。如果你想象该类型的“未衰减”版本为,即
int x[][]
——显然是无效的C。如果您想在C中传递二维数组,您有几个选项:

  • 传递带有大小参数的一维数组

    void func(int n, int x[])
    {
        x[2*n + 5] = 900;
    }
    
  • 使用指向行的指针数组。如果你有真正的2D数据,这会有点笨重

    void func(int *x[])
    {
        x[2][5] = 900;
    }
    
  • 使用固定尺寸

    void func(int x[][5])
    {
        x[2][5] = 900;
    }
    
  • 使用可变长度数组(仅限C99,因此它可能不适用于Microsoft编译器)

这是一个经常出现的问题,即使对C语言的老手来说也是如此。许多语言缺乏对真实的、可变大小的多维数组(C++、Java、Python)的固有的“开箱即用”支持,尽管有一些语言(Common Lisp、Haskell、Fortran)。您将看到许多使用数组数组或手动计算数组偏移量的代码。

注意:
当Q被标记为C++时,下面的答案被添加,并且它从C++的角度回答。标签被改变为只有C,两个样本在C.</P>中都是有效的。 是的,你的推理是正确的。
如果尝试编译,编译器给出的错误是:

parameter ‘p_array’ includes pointer to array of unknown bound ‘char []’

在编译时,C++的数组大小需要固定。C++标准也禁止可变长度数组(VLA)。一些编译器支持扩展,但这是非标准一致性。

< P>这两个声明非常不同。在函数参数声明中,<代码>直接应用于参数名的完全等同于一个*,因此您的第一个声明在所有方面都与此完全相同:

function(char **p_array);
但是,这不会递归地应用于参数类型。您的第二个参数的类型为
char(*)[]
,它是指向未知大小数组的指针-它是指向不完整类型的指针。您可以愉快地使用此类型声明变量-以下是有效的变量声明:

char (*p_array)[];
就像指向任何其他不完整类型的指针一样,您不能在此变量(或函数参数)上执行任何指针运算-这就是错误产生的原因。请注意,
[]
运算符被指定为
a[i]
*(a+i)相同
,因此运算符不能应用于指针。当然,您可以愉快地将其用作指针,因此这是有效的:

void function(char (*p_array)[])
{
    printf("p_array = %p\n", (void *)p_array);
}
此类型还与指向任何其他固定大小的
char
数组的指针兼容,因此您也可以执行以下操作:

void function(char (*p_array)[])
{
    char (*p_a_10)[10] = p_array;

    puts(*p_a_10);
}
…即使是这样:

void function(char (*p_array)[])
{
    puts(*p_array);
}
(尽管这样做没有什么意义:您也可以使用类型
char*
声明参数)


请注意,尽管允许使用
*p_数组
,但不允许使用
p_数组[0]

是(2)指向字符数组的指针或指向字符数组的函数指针?@Mahesh,第二个是指向字符数组的指针(但需要具有固定大小)。此外,字符数组是一种数据类型;我们不能让函数指针指向它。您可以指定为,
char(*p)[3]=&a;
其中
char a[3];
@iammilind:问题标题是“C"迪特里希编译:C++是一个C++语言,标题是C和C++,C++中的行为不同。C允许VLA而C++不允许。@克里斯:我道歉。我经常出错,使用编译器<代码> -PANANTIC-ANSI-WALW-WOTAU/COD>双重检查,如找到合适的T段。需要更多的时间。(适当的部分是n1570第6.7.6.2节和第6.7.6.3节,尽管您基本上必须阅读这两部分才能确定这是正确的。它们不是VLA,而是不完整类型的数组。VLA在C99中是新的,但不完整类型的数组与C本身一样古老。)这是关于C还是C++的问题?标题是“C”,但是标签都是“两个”,答案是不同的,这取决于你使用的是什么…@ Dietrich Epp -C和C++是不同的,但是TH是不同的。
void function(char (*p_array)[])
{
    printf("p_array = %p\n", (void *)p_array);
}
void function(char (*p_array)[])
{
    char (*p_a_10)[10] = p_array;

    puts(*p_a_10);
}
void function(char (*p_array)[])
{
    puts(*p_array);
}