繁体   English   中英

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

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

我是C的新手并且坚持“如何将多维数组传递给函数”。 我知道你必须传递列大小,这样如果你想从a[0][0]a[1][0]它可以计算一维数组的大小,并可以跳过它。

我写了一个小程序:

#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);
}

我期望这段代码会打印字母c ,因为temp最初指向'a' ,一旦我们递增它,它将跳过第一个1-d数组并转到第二个1-d数组的第一个元素'c' 但是我认为这种方式不起作用。

请解释编译器如何计算这些地址。

指针算术很好。 你忘了取消引用*temp ,它有char[2]类型。

将其更改为**temp ,您将获得输出c

对于函数参数char temp[][2]temp衰减为指针。 但仅限于第一(外)维度。 所以它实际上是一个指向char数组[2]的指针

正如您已经假设的那样,递增指针将使其前进到下一个外部索引。

因此,您必须使用(*temp)[0]**temp来获取第一个元素。 **temp有效,因为*temp是一个数组本身,所以它衰减到指向内部数组的第一个元素的指针。 第二个(左) *然后取消引用这个指针: c

请注意,虽然它使用与char **temp相同的语法,但它们根本不同。 指针不是一个数组,在这里,递增temp只会前进一个指针的大小,这不是你想要的。

请注意,初始化程序最好是根据2维性质:

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

这可以确保您获得内部数组的正确值,这是一种很好的做法。 省略非嵌套表单中的值将导致内部数组的序列错误。 当至少启用了推荐警告( -Wall ,gcc会警告缺少大括号。

除了当它是的操作数sizeof或一元&操作员,或者是一个字符串被用来初始化一个声明另一个数组,类型“的N元件阵列的表达 T将被转换(“衰变”)”,以“指向T指针”类型的表达式,表达式的值将是数组中第一个元素的地址。

main ,函数调用foo(arr)中的表达式arr的类型是“2元素数组char的2元素数组”; 因为它不是sizeof或一元&运算符的操作数,所以它“衰变”为类型为“指向2元素char数组的指针”或char (*)[2]的表达式。

因此,参数tempchar (*)[2] ,它指向arr的第一个元素。 参数声明char temp[][2]等同于char (*temp)[2] 表达式*temp等同于temp[0] ,并且都具有类型“ char 2元素数组”( char [2] )。 表达式temp + 1为您提供下一个2元素char数组的地址,因此*(temp + 1)等效于temp[1]

这是一个总结所有这些的表格:

    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'

所以,在你的print语句中,你会写

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

要么

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

要么

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

表达式arr&arr*arrarr[0]&arr[0]*arr[0]&arr[0][0]都产生相同的 - arr的第一个元素的地址(记住,数组的地址和数组的第一个元素的地址是相同的)。 他们的类型不同。

请注意, &temp为我们提供了 &arr 不同的值。 由于temp被声明为指针而不是数组,因此&temp为我们提供了指针变量的地址。

图片可能会有所帮助:

      +---+    
 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