1

我正在学习 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


我学到的是 --> 对于一维数组:

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

这里 arr 和 &arr 不应该被认为是相同的(虽然它们打印相同的值,但是这个信息的意义是完全不同的)。这就是为什么 arr+1 和 &arr+1 也不相同的原因。&arr 给出了一个数据类型的地址,该数据类型是 7 个整数的容器,这就是为什么 &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};

now arris here 也是一个指向数组单个元素的指针,soarrarr+1是其连续元素的地址(这些元素是{1,2,3,4}and {5,6,7,8})_ 并且以相同的方式&arr给出&arr+1具有 2x4=8 元素的两个数组的基地址,所以to&arr&arr+1是两个大小相似的数组的地址。所以

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

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

1)arr(给出在两个内部数组之间选择哪个元素)
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]

这个概念也可以扩展到 3 维数组,但这是每个初学者都应该理解的最低要求。如果我在概念上或句法上的任何地方有错误,请纠正我。

4

6 回答 6

2

因为arr是二维数组。

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

于 2013-10-03T11:12:13.433 回答
1
printf("%d",*(*(arr+1)+2) );

把它分成两个语句

*(arr+1) means arr[1]

像这样

*(arr[1] + 2) means arr[1][2]
于 2013-10-03T11:18:18.143 回答
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
                  };  

将数组名称传递arrprintf意味着它衰减到指向数组的第一个元素(行0)的指针arr[2]并且是类型int (*)[4](认为二维数组是 2 个元素的 1D 数组,每个元素是 4 个元素的数组)。

我认为要转到第二个数组,它应该是 &arr+1。

arr + 1指向数组的第二个元素(行1arr[2]而不是数组行的第二个元素1arr[2][4]。通过这样做arr + 1,您不仅添加1到指针arr(衰减后),而且添加了将元素存储在一行中所需的总字节数。
让我们通过一个简单的例子来理解这一点:考虑引用isarr的地址100和大小。然后意味着你在做。 因此,取消引用将给出整行,而取消引用将给出 row 的第三个元素,即 7。 而且,用于。要打印地址(指针值),请使用int4arr + 1100 + (4-1)*4 = 112
(arr + 1)1(*(arr+1)+2)1
%uunsigned integer%p第一个printf语句中的说明符。

于 2013-10-03T11:33:40.700 回答
0

When accessing char arr[ROW_COUNT][COLUMN_COUNT], arr[row][col] is equivalent to address_of_arr[col + (row * ROW_COUNT)]. Once you've wrapped your head around that it will all make a lot more sense.

arr and arr+1 should not be adjacent, there should be a difference of 4 bytes. Exactly what result are you seeing?

于 2013-10-03T11:31:25.597 回答
0

arr+1并且&arr+1在这种情况下是完全相同的东西,因为arr是一个数组隐式降级为指针,或者显式地获取其地址,这相当于同一件事。

如您所知,将 1 加到数组中的第二个元素。Andarr是一个数组数组,所以它的第二个元素是第二个子数组。

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

于 2013-10-03T11:13:35.290 回答
0

您使用的数组是character这样的,每个字段占用 1 个字节。arr并且arr+1不会在相邻的位置。

我认为当您检查 arr 和 arr+1 的输出时,差异为 4,因此请记住整数并告诉它位于相邻位置。

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

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

将您的数据类型从更改charint您将了解更多。

检查以下程序的输出。

#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。

于 2013-10-03T11:32:38.100 回答