复杂的字符串和数组声明

时间:2013-10-03 11:08:46

标签: c arrays

我正在研究C语言的基础知识,我对字符串和数组感到困惑。

    #include<stdio.h>
    int main()
    {
      char arr[2][4] = {1,2,3,4,5,6,7,8};
      printf("%u %u\n",arr,arr+1);
      printf("%d",*(*(arr+1)+2) );
      return 0;
    }

此处arrarr+1是相邻的位置,但在第二个printf arr+1中直接转到第二个数组的零索引元素。这怎么合法?我原以为要转到第二个数组应该是&arr+1


我学到的是 - &gt;对于一维数组:

  arr[7]={1,2,3,4,5,6,7};

这里arr和&amp; arr不应该被认为是相同的(尽管它们打印相同的值,但这种信息的意义完全不同)。这就是为什么arr + 1和&amp; arr + 1也不一样。 &amp; arr给出数据类型的地址,该数据类型是7个整数的容器,这就是为什么&amp; arr + 1进入后续数组类型,也就是7个整数的容器。 所以

arr = 5796 , &arr = 5796    (both are base address but arr is the address of    
                   1st element while &arr is the address of the whole array)
arr+1 = 5800 ,&arr+1 = (5796+(7X4))=5797+28 = 5825(this is address of some 
new array)

对于二维数组,概念是相同的:

arr[2][4]={1,2,3,4,5,6,7,8};

现在arr此处也是一个指向数组单个元素的指针,因此arrarr+1是其后续元素的地址(这些元素为{1,2,3,4}{5,6,7,8})_ 并且以相同的方式&arr&arr+1给出了两个具有2x4 = 8个元素的数组的基址,因此&arr&arr+1是两个相似大小的数组的地址接连不断。 所以

 arr = 5796 , arr+1 = 5796+(4*3)=5796+12 = 5808 
 &arr = 5796 , &arr+1 = 5796+(4*7)=5796+ 28= 5824

现在我们可以在二维数组中看到到达一个单独的元素,有两个地址关联。

1)ar r(它给出了在两个内部数组之间选择的元素)
2)*arr(给出该特定元素(数组)中的哪个元素

因此,如果我们想要访问数据,我们需要取消引用两次。

arr=5796(first array), *arr=5796(first element address), **arr = 1 (1st element)
arr+1=5812(second array), *(arr+1) = 5812(first element address), *(*(arr+1))=5(first element)
arr=5796,*arr=5796, *arr+1=5796+1(second element), *(*arr+1)=2 (second element)

现在是数组的语法:

   *arr = arr[0]
   **arr = arr[0][0]
   *arr+1 = arr[0]+1
   **arr+1 = arr[0][0]+1
   *(*arr+1) = *(arr[0]+1) = arr[0][1]
   *(*(arr+1)+1) = *(arr[1]+1) = arr[1][1]

还有其他一些编写数组的方法

      3[arr[1]] = arr[1][3]
      -3[arr[1]] = -arr[1][3]
      *(1[arr]+2) = *(arr[1]+2) = arr[1][2]

这个概念也可以扩展到三维数组,但这是每个初学者应该理解的最小值。如果我在概念上或语法上错了,请更正我。

6 个答案:

答案 0 :(得分:2)

因为arr是二维数组。

*(*(arr+1)+2))相当于arr[1][2]

答案 1 :(得分:1)

printf("%d",*(*(arr+1)+2) );

将其分为两个陈述

*(arr+1) means arr[1]
像这样

*(arr[1] + 2) means arr[1][2]

答案 2 :(得分:1)

宣言

char arr[2][4] = {1,2,3,4,5,6,7,8};  

表示

char arr[2][4] = { 
                     {1,2,3,4},   // row 0
                     {5,6,7,8}    // row 1
                  };  

将数组名称arr传递给printf意味着它衰减指向数组0的第一个元素(行arr[2])并且类型为{{1 (将2D数组视为2个元素的1D数组,每个元素包含4个元素的数组)。

  

我原以为要转到第二个数组应该是&amp; arr + 1.

int (*)[4]指向数组arr + 1的第二个元素(行1)(而不是数组{{1}的行arr[2]的第二个元素}} 的)。通过执行1,您不会仅将arr[2][4]添加到指针arr + 1(在衰减之后),而是添加将元素存储在一行中所需的总字节数。
让我们通过一个简单的例子来理解这一点:考虑1引用地址arrarr的大小是100。然后int表示您正在做4 因此解除引用arr + 1将提供整行100 + (4-1)*4 = 112,而解除引用(arr + 1)将提供行1的第3个元素,即7。 此外,(*(arr+1)+2)用于1。要打印地址(指针值),请在第一个%u语句中使用unsigned integer说明符。

答案 3 :(得分:0)

此上下文中的

arr+1&arr+1完全相同,因为arr是一个隐式降级为指针的数组,或者显式地使用其地址,这相当于同样的事情。

如你所知,向数组添加1会转到第二个元素。 arr是一个数组数组,因此它的第二个元素是第二个子数组。

如果您想要第一个子阵列的第二个元素,请尝试arr[0]+1,这相当于&arr[0][1]

答案 4 :(得分:0)

访问char arr[ROW_COUNT][COLUMN_COUNT]时,arr[row][col]相当于address_of_arr[col + (row * ROW_COUNT)]。一旦你绕过它,它就会更有意义。

arrarr+1不应该相邻,应该有4个字节的差异。究竟是什么结果?

答案 5 :(得分:0)

您使用的

数组是character,因此每个字段占用1个字节。 arrarr+1不会位于相邻位置。

我认为当你检查arr的输出和arr + 1的差值为4时,你要记住整数并告诉它在相邻位置。

&arr[0] =第一行第一个元素的地址

&arr[1] =第二行第一个元素的地址

将您的数据类型从char更改为int,您将了解更多。

检查以下程序的输出。

#include<stdio.h>
int main()
{
 char arr[2][4] = { 1,2,3,4,
                    5,6,7,8 };

 printf("%u\n", &arr[0][0]);
 printf("%u\n", &arr[0][4]);

 printf("%u\n", &arr[1][0]);
 printf("%u\n", &arr[1][4]);

 printf("%d\n",*(*(arr+1)+2) ); // equal to arr[1][2]
 printf("%d\n", *(arr[1] + 2) );
 printf("%d\n", arr[1][2]);

 return 0;
}

输出:

3214594184
3214594188
3214594188
3214594192
7
7
7

以上程序会给出一些警告,用%p替换%u。