Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C指向数组的指针/指针数组消歧_C_Arrays_Pointers_Variable Declaration - Fatal编程技术网

C指向数组的指针/指针数组消歧

C指向数组的指针/指针数组消歧,c,arrays,pointers,variable-declaration,C,Arrays,Pointers,Variable Declaration,以下声明之间有什么区别: int* arr1[8]; int (*arr2)[8]; int *(arr3[8]); 理解更复杂的声明的一般规则是什么 int* arr[8]; // An array of int pointers. int (*arr)[8]; // A pointer to an array of integers 第三个与第一个相同 一般规则是。随着函数指针的出现,它可能变得更加复杂。我不知道它是否有正式名称,但我称它为Right-Left-Thingy(TM) 从变

以下声明之间有什么区别:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
理解更复杂的声明的一般规则是什么

int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
第三个与第一个相同


一般规则是。随着函数指针的出现,它可能变得更加复杂。

我不知道它是否有正式名称,但我称它为Right-Left-Thingy(TM)

从变量开始,然后向右、向左、向右……依此类推

int* arr1[8];
arr1
是一个由8个指向整数的指针组成的数组

arr2
是指向8个整数数组的指针(左括号)

arr3
是一个由8个指向整数的指针组成的数组

这将帮助您处理复杂的声明。

按照K&R的建议使用该程序

$cdecl
键入“帮助”或“?”以获取帮助
cdecl>explain int*arr1[8];
将arr1声明为指向int的指针的数组8
cdecl>explain int(*arr2)[8]
将arr2声明为指向int数组8的指针
cdecl>explain int*(arr3[8])
将arr3声明为指向int的指针的数组8
cdecl>
它的工作方式也是相反的

cdecl>将x声明为函数指针(void)返回浮点指针
浮动*(*x)(无效)

最后两个问题的答案也可以从C中的黄金法则中扣除:

声明跟随使用

int(*arr2)[8]

如果取消对arr2的引用,会发生什么情况?得到一个由8个整数组成的数组

int*(arr3[8])

如果从
arr3
获取元素,会发生什么情况?你得到一个指向整数的指针

这也有助于处理指向函数的指针。以sigjuice为例:

float*(*x)(无效)

取消引用
x
时会发生什么情况?您可以得到一个无需参数即可调用的函数。当你叫它时会发生什么?它将返回一个指向浮动的指针

不过,运算符优先级总是很棘手。然而,使用括号实际上也会令人困惑,因为声明遵循use。至少在我看来,
arr2
直观上看起来像是一个由8个指向int的指针组成的数组,但实际上恰恰相反。只是需要一些时间来适应。有足够的理由总是在这些声明中添加注释,如果你问我:)

编辑:示例

顺便说一句,我刚刚偶然发现了以下情况:一个函数有一个静态矩阵,它使用指针算法来查看行指针是否超出范围。例如:

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

#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))

int *
put_off(const int newrow[2])
{
    static int mymatrix[3][2];
    static int (*rowp)[2] = mymatrix;
    int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);

    memcpy(rowp, newrow, sizeof(*rowp));
    rowp += 1;
    if (rowp == border) {
        rowp = mymatrix;
    }

    return *rowp;
}

int
main(int argc, char *argv[])
{
    int i = 0;
    int row[2] = {0, 1};
    int *rout;

    for (i = 0; i &lt; 6; i++) {
        row[0] = i;
        row[1] += i;
        rout = put_off(row);
        printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
    }

    return 0;
}
请注意,border的值永远不会更改,因此编译器可以对其进行优化。这与您最初可能希望使用的不同:
const int(*border)[3]
:它将border声明为指向3个整数数组的指针,只要变量存在,该数组的值就不会改变。然而,该指针可随时指向任何其他此类数组。相反,我们希望参数具有这种行为(因为此函数不会更改任何整数)。声明跟随使用


(附言:请随意改进此示例!)

我认为我们可以使用简单的规则

example int * (*ptr)()[];
start from ptr 
ptr
是指向的指针” 向右转现在向左转它是a “出来,向右走”所以 指向一个函数,该函数不带任何参数“向左”,并返回指向的指针“向右”
指向整数的指针中的整数数组“左移”

,如果指针递增,则它将进入下一个整数


在指针数组中,如果指针递增,它将跳转到下一个数组。根据经验法则,右一元运算符(如
[]
()
,等等)优先于左一元运算符。因此,
int*(*ptr)([]);
将是指向将指针数组返回int的函数的指针(从括号中取出后,尽快获取正确的运算符)

以下是我的解释:

int *something[n];
关于优先级的注意事项:数组下标运算符(
[]
)的优先级高于 取消引用运算符(
*

因此,这里我们将在
*
之前应用
[]
,使该语句等效于:

int *(something[i]);
请注意声明的意义:
int num
表示
num
int
int*ptr
int(*ptr)
表示(位于
ptr
的值)是 一个
int
,它使
ptr
成为指向
int
的指针

这可以理解为,(某物第i个索引处的值)是一个整数。所以,(某物第i个索引处的值)是一个(整数指针),它使某物成为一个整数指针数组

第二个,

int (*something)[n];
要理解此陈述,您必须熟悉以下事实:

关于数组指针表示的注意:
somethingElse[i]
相当于
*(somethingElse+i)


因此,用
(*something)
替换
(*something)
,我们得到了
*(*something+i)
,根据声明,它是一个整数。因此,
(*something)
给了我们一个数组,使得某个数组等价于(指向数组的指针).

我想第二个声明让很多人感到困惑。这里有一个简单的方法来理解它

让我们有一个整数数组,即
intb[8]

我们还有一个指向B的变量a。现在,a处的值是B,即
(*a)==B
。因此a指向一个整数数组。在您的问题中,arr类似于a


类似地,在
int*(*C)[8]
中,C是指向整数指针数组的指针。

下面是一个有趣的网站,它解释了如何在C中读取复杂类型:

在此声明中,
arr1
是一个由5个指向整数的指针组成的数组。 原因:方括号的优先级高于*(解除限制运算符)。 在这种类型中,行数是固定的(这里是5),但列数是可变的

int (*arr2)[5]
example int * (*ptr)()[];
start from ptr 
int *something[n];
int *(something[i]);
int (*something)[n];
int *arr1[5]
int (*arr2)[5]