简体   繁体   English

指针算术和c中的二维数组?

[英]Pointer arithmetic and 2-D array in c?

I am new to C and got stuck on "How to pass multidimensional array to a function". 我是C的新手并且坚持“如何将多维数组传递给函数”。 I do understand that you have to pass column size so that if you want to go from a[0][0] to a[1][0] it can calculate the size of 1-D array and can jump over it. 我知道你必须传递列大小,这样如果你想从a[0][0]a[1][0]它可以计算一维数组的大小,并可以跳过它。

I have written a small program: 我写了一个小程序:

#include<stdio.h>
void foo(char[][2]);
int main()
{
     char arr[2][2] = {'a','b','c','d'};

     foo(arr);
     return 0;
}

void foo(char temp[][2])
{
      temp++;
      printf("%c",*temp);
}

I expected that this code will print the letter c , since temp initially points to 'a' and once we increment it, it will skip over first 1-d array and go to first element of second 1-d array which is 'c' . 我期望这段代码会打印字母c ,因为temp最初指向'a' ,一旦我们递增它,它将跳过第一个1-d数组并转到第二个1-d数组的第一个元素'c' But it does not work that way I guess. 但是我认为这种方式不起作用。

Please explain the how compiler computes these addresses. 请解释编译器如何计算这些地址。

The pointer arithmetic is good. 指针算术很好。 You just forgot to dereference *temp , which has type char[2] . 你忘了取消引用*temp ,它有char[2]类型。

Change it to **temp , and you'll get an output c . 将其更改为**temp ,您将获得输出c

For function argument char temp[][2] , temp decays to a pointer. 对于函数参数char temp[][2]temp衰减为指针。 But only for the first (outer) dimension. 但仅限于第一(外)维度。 So it is effectively a pointer to array [2] of char . 所以它实际上是一个指向char数组[2]的指针

Incrementing the pointer will advance it to the next outer index, as you already assumed. 正如您已经假设的那样,递增指针将使其前进到下一个外部索引。

So, you either have to use (*temp)[0] or **temp to get the first element. 因此,您必须使用(*temp)[0]**temp来获取第一个元素。 **temp works, because *temp is an array itself, so it decays to a pointer to the first element of the inner array. **temp有效,因为*temp是一个数组本身,所以它衰减到指向内部数组的第一个元素的指针。 The second (left) * then dereferences this pointer: c . 第二个(左) *然后取消引用这个指针: c

Note that, allthough it uses the same syntax like char **temp , they are fundamentally different. 请注意,虽然它使用与char **temp相同的语法,但它们根本不同。 A pointer is not an array and here, incrementing temp will only advance by the size of a pointer, which is not what you want. 指针不是一个数组,在这里,递增temp只会前进一个指针的大小,这不是你想要的。

Note that the initializer would better be according to the 2-simensional nature: 请注意,初始化程序最好是根据2维性质:

{ { 'a', 'b' } , { 'c', 'd' } }

This ensures you get the correct values for the inner arrays and is good practice. 这可以确保您获得内部数组的正确值,这是一种很好的做法。 Omitting a value in the non-nested form will result in wrong sequence for the inner array. 省略非嵌套表单中的值将导致内部数组的序列错误。 When having enabled the recommended warnings ( -Wall ) at least , gcc warns about missing braces. 当至少启用了推荐警告( -Wall ,gcc会警告缺少大括号。

Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T " will be converted ("decay") to an expression of type "pointer to T ", and the value of the expression will be the address of the first element in the array. 除了当它是的操作数sizeof或一元&操作员,或者是一个字符串被用来初始化一个声明另一个数组,类型“的N元件阵列的表达 T将被转换(“衰变”)”,以“指向T指针”类型的表达式,表达式的值将是数组中第一个元素的地址。

In main , the type of the expression arr in the function call foo(arr) is "2-element array of 2-element array of char "; main ,函数调用foo(arr)中的表达式arr的类型是“2元素数组char的2元素数组”; since it isn't the operand of the sizeof or unary & operators, it "decays" to an expression of type "pointer to 2-element array of char ", or char (*)[2] . 因为它不是sizeof或一元&运算符的操作数,所以它“衰变”为类型为“指向2元素char数组的指针”或char (*)[2]的表达式。

Thus, the parameter temp is type char (*)[2] , and it points to the first element of arr . 因此,参数tempchar (*)[2] ,它指向arr的第一个元素。 The parameter declaration char temp[][2] is equivalent to char (*temp)[2] . 参数声明char temp[][2]等同于char (*temp)[2] The expression *temp is equivalent to temp[0] , and both have type "2-element array of char " ( char [2] ). 表达式*temp等同于temp[0] ,并且都具有类型“ char 2元素数组”( char [2] )。 The expression temp + 1 gives you the address of the next 2-element array of char , so *(temp + 1) is equivalent to temp[1] . 表达式temp + 1为您提供下一个2元素char数组的地址,因此*(temp + 1)等效于temp[1]

Here's a table to summarize all of that: 这是一个总结所有这些的表格:

    Expression        Type            Decays To         Value
    ----------        ----            ---------         -----
           arr        char [2][2]     char (*)[2]       &arr[0][0]
          *arr        char [2]        char *            arr[0]
          &arr        char (*)[2][2]  n/a               &arr[0][0]
        arr[i]        char [2]        char *            &arr[i][0]
       *arr[i]        char            n/a               arr[i][0]
       &arr[i]        char (*)[2]     n/a               &arr[i][0]
     arr[i][j]        char            n/a               arr[i][j]

          temp        char (*)[2]     n/a               &arr[0][0]
         *temp        char [2]        char *            arr[0]
         &temp        char (**)[2]    n/a               addr of temp variable
       temp[i]        char [2]        char *            &arr[i][0]
      *temp[i]        char            n/a               arr[i][0]
      &temp[i]        char (*)[2]     n/a               &arr[i][0]
    temp[i][j]        char            n/a               arr[i][j]

       arr + 1        char [2][2]     char (*)[2]       &arr[1][0]
    *(arr + 1)        char [2]        char *            arr[1]
      temp + 1        char (*)[2]     n/a               &arr[1][0]
   *(temp + 1)        char [2]        char *            arr[1]

     arr[0][0]        char            n/a               'a'
     arr[0][1]        char            n/a               'b'
     arr[1][0]        char            n/a               'c'
     arr[1][1]        char            n/a               'd'

        **temp        char            n/a               'a'
      *temp[0]        char            n/a               'a'
    temp[0][0]        char            n/a               'a'

  **(temp + 1)        char            n/a               'c'
      *temp[1]        char            n/a               'c'
    temp[1][0]        char            n/a               'c'

So, in your print statement, you would write either 所以,在你的print语句中,你会写

printf("%c", **temp); // temp == &arr[1][0] after temp++

or 要么

printf("%c", *temp[0]); // temp[0] == arr[1] after temp++

or 要么

printf("%c", temp[0][0]); // temp[0][0] == arr[1][0] after temp++

The expressions arr , &arr , *arr , arr[0] , &arr[0] , *arr[0] , and &arr[0][0] all yield the same value - the address of the first element of arr (remember that the address of the array and the address of the first element of the array are the same). 表达式arr&arr*arrarr[0]&arr[0]*arr[0]&arr[0][0]都产生相同的 - arr的第一个元素的地址(记住,数组的地址和数组的第一个元素的地址是相同的)。 They just differ in type. 他们的类型不同。

Note that &temp gives us a different value than &arr . 请注意, &temp为我们提供了 &arr 不同的值。 Since temp was declared as a pointer, not an array, &temp gives us the address of the pointer variable. 由于temp被声明为指针而不是数组,因此&temp为我们提供了指针变量的地址。

A picture may help: 图片可能会有所帮助:

      +---+    
 arr: |'a'|  arr[0][0] <------------------+ before temp++
      +---+                               |
      |'b'|  arr[0][1]                    |
      +---+                               |
      |'c'|  arr[1][0] <--+ after temp++  |   
      +---+               |               |
      |'d'|  arr[1][1]    |               |
      +---+               |               |
       ...                |               |
      +---+               |               |
temp: |   |---------------+---------------+
      +---+

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM