具有迭代数组功能的优先级,括号,指针

时间:2019-01-02 19:42:58

标签: c

我正在自学一点C,并且进行了一次练习,希望确保自己完全理解。练习要求我将指向多维整数数组的指针传递给函数,然后遍历该数组。因此,我先使用打印功能,然后再进行输入以填充数组。我尝试了各种方法,但是在类型转换和迭代指针上找到了一些代码之后,我有了下面的程序,该程序似乎可以工作,但我不太了解发生了什么。在我的评论中,我有标记为1-3的问题,是指代码下方的问题。我希望有人比我能启发我。

//passing multi-Array to a simple print function
#include <stdio.h>

//simple print function prototype
void printMyArr(int (*pt)[4]);

int main()
{
    //declare and initialize a multi-array. I picked 4x4 and some arbitrary 
    //numbers for simplicity's sake

    int myArr[4][4] = { {12, 16, 19, 20}, 
                        {5, 99, 102, 200}, 
                        {12, 20, 25, 600},
                        {65, 66, 999, 1000} };

    //declare a pointer to an array of integers and an int for a loop counter
    int (*pt)[4], counter;

    //initialize the pointer
    pt = myArr;

    //for loop calling printMyArr function to iterate through arrays -- or this is what I understand it to mean
    for(counter=0; counter<4; counter++)
        printMyArr(pt++);   //<-------------Question 1
    return 0;
}

//function called to print array elements to the console
void printMyArr(int(*pt)[4])
{
    //declare a counter....and apparently another pointer
    int counter, *p;

    //initialize new pointer to old pointer and type cast array as int
    p = (int *)pt;          //<-------------Question 2

    //for loop to iterate through elements of array -- or this is what I understand it to mean
    for(counter=0; counter<4; counter++)
        printf("\n\n\n%d", *p++);  //<------Question 3
}

问题1:在这里,我将指针传递给了函数,然后我一直在思考:“这个循环在迭代什么?”。我以为我要递增指向每个数组中每个第一个元素的指针(myArr[0][0]myArr[1][0]myArr[2][0]myArr[3][0])的正确性吗?另外,我是否假设此行的语法本质上是这样说的:“执行传递当前指针的函数,完成后传递当前指针,然后递增指针。”

问题2:这是我最困惑的地方。经过大量的挖掘之后,我发现该部分可以使其正确运行,并且我知道这是如何工作的,但是为什么呢?

问题3:我是否正确认为自己在这里增加了每个元素?

所以

1:传递指定的指针-> myArr[0][0],然后打印myArr[0][0]myArr[0][1]myArr[0][2]myArr[0][3]中的值,然后递增指针{ {1}}

2:传递指定的指针-> myArr[1][0],然后将myArr[1][0]myArr[1][0]myArr[1][1]myArr[1][2]增量指针中的值打印到{{1 }}

3:传递指定的指针-> myArr[1][3],然后将myArr[2][0]myArr[2][0]myArr[2][0]myArr[2][1]增量指针中的值打印到{{1 }}

4:传递指定的指针-> myArr[2][2],然后将myArr[2][3]myArr[3][0]myArr[3][0]myArr[3][0]增量指针中的值打印到{{1 }},如果是这种情况,那么由于不应该有myArr[3][1],指针指向什么呢?

3 个答案:

答案 0 :(得分:2)

  

问题1:在这里,我将指针传递给了函数,然后我一直在思考:“这个循环在迭代什么?”。我是否认为我正在递增指向每个数组中每个第一个元素的指针(myArr [0] [0],myArr [1] [0],myArr [2] [0],myArr [3] [ 0])?

或多或少。 ptmyArr的地址开始。您知道数组中有4件事,因此您循环4次,每次访问pt后都将printMyArr递增一次,以传递给printMyArr“顶层”,“外部”数组。然后pt遍历内部数组的4个元素以显示每个数字。

  

此外,我是否假设此行的语法本质上是这样说的:“执行传递当前指针的函数,然后在完成后传递指针,然后递增指针。”

从功能上讲,是的。从技术上讲,操作顺序如下:

1)获得pt的值 2)递增pt 3)调用函数,从步骤1开始传递pt的先前值

pt++作为pt++调用的一部分而增加,但是pt++的值为旧值。作为函子的参数,必须在传递给函数的函数运行前 评估p = (int *)pt; for(counter=0; counter<4; counter++) printf("\n\n\n%d", *p++); 。但是,时间与在针对您的案例运行该函数后立即进行评估的时间相同。

让我们一起回答问题2和3,因为它们都是答案的一部分。

  

问题2:这是我最困惑的地方。经过大量的挖掘之后,我发现该部分可以使其正确运行,并且我知道这是如何工作的,但是为什么呢?

     

问题3:我是否正确地认为我要在此处增加每个元素?

p

p存储一个整数地址。您将其设置为内部数组第一个元素的地址(可以这么说,它是内部数组本身的地址)。然后,知道数组中有4个元素,就可以循环4次,对pt进行类似于外部数组p的指针后递增操作。

第一次迭代pt*p相同,即存储器中4个整数值中第一个整数的地址。 *p++取消引用指针,将获取第一个整数。由于p的运算顺序(++为最高优先级,而对*的引用为更低),它返回p处的整数,而p指向该地址的下一个整数地址下一个循环。

通常为casting values in C should be avoidid whenever possible。您只需要在这里进行解引用即可将pt指向整数集。 *pt在内存中包含4个整数(内部数组)的连续集合的4个地址(外部数组)之一的地址。 int* p=*pt; 处的值是内存中4个连续整数的“当前”组的地址。所以您可以简单地说,

USE

这不是任意转换类型,非常简单明了。 (感谢@WhozCraig)

答案 1 :(得分:1)

多个D数组作为连续数组保留在内存中,因此,如果您有数组[2] [2],它将分配4个连续的sizeof(int)。您需要定义array [] [COL]的原因是让编译器知道应该如何执行指针算术。

所以-对于Q1,您是对的,每次增加(sizeof(int)* COL)都这样做。因此,每次您移动一行。

现在Q2-对于要一次打印一个int值的每一行,因此当您有int * p-时,这意味着每个增量都由sizeof(int)完成。

Q3-增量是指针,而不是值,如果在主体中进行其他打印很容易自己看到。

希望有帮助,祝您好运!

答案 2 :(得分:0)

2D myArr数组的内存视图如下所示:

        myArr
         ---------------------
myArr[0] | 12 | 16 | 19 | 20 |
         ---------------------
myArr[1] | 5  | 99 |102 |200 |
         ---------------------
myArr[2] | 12 | 20 | 25 |600 |
         ---------------------
myArr[3] | 65 | 66 |999 |1000|
         ---------------------
  

Question 1: Here, I've passed the pointer to the function and I keep thinking, "What is this loop iterating over?". Am I correct in thinking that I am incrementing the pointer to each of the first elements in each array (myArr[0][0], myArr[1][0], myArr[2][0], myArr[3][0])? Also, am I correct in assuming that the syntax of this line is in essence saying: "Execute the function passing the current pointer and THEN when it's done, increment the pointer."?

问题1的答案:

int (*pt)[4]

pt是指向4整数数组的指针。此声明

pt = myArr;

使pt指向1D myArr数组的第一个2D数组。它类似于:

pt = &myArr[0];

这两个语句的影响将是这样的:

pt--------|
         \|/
         ---------------------
myArr[0] | 12 | 16 | 19 | 20 |
         ---------------------

当您递增指针时,它会按照指针可以指向的对象大小逐步递增。在这里

printMyArr(pt++);

首先将pt指针值传递给printMyArr(),然后将pt递增,由于其类型为int (*)[4],这意味着它可以指向一个4整数数组,因此在递增之后,pt将指向地址(即address pointing to + size of array of 4 int),即myArr[1]地址。

请注意,

for(counter=0; counter<4; counter++)
        printMyArr(pt++);

与此相同:

for(counter=0; counter<4; counter++)
        printMyArr(&myArr[counter]);
                   ^^^^^^^^^^^^^^^
  

Question 2: This is what has me the most confused. After quite a bit of digging I found this bit to make it run right and I realize this is how it works, but why?

问题2的答案:

这里

p = (int *)pt;   // pt is pointer to an array of `4` integer

如果删除(int *)强制转换,则会发现编译器在此语句上发出警告消息。原因是ppt不是兼容的指针类型。 p的类型为int *,而pt的类型为int (*)[4]。这种不兼容的指针分配之所以起作用,是因为尽管类型不同,但数组的地址和数组的第一个元素的地址在数字上是相同的。相反,您应该

p = &(*pt)[0];

根据C Standards#6.5.2.1

  

下标运算符[]的定义是E1 [E2]等于(*(((E1)+(E2))))

按此规则

&(*pt)[0] --> &(*((*pt)+(0))) --> ((*p)+(0)) --> *p

The operator & is used to get the address and the operator * is used for dereferencing. These operators cancel the effect of each other when used one after another.

因此,此声明

p = &(*pt)[0];

与此声明相同

p = *pt;
  

Question 3: Am I correct thinking that I am incrementing each element here?

问题3的答案:

是的。
p是指向4整数数组的第一个元素的指针,其类型为int *,即它可以指向一个int的对象。当您执行*p++时,这将首先取消引用p并在其指向的地址处获取值,然后p将递增并指向数组的下一个元素。