我正在研究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;
}
此处arr
和arr+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
此处也是一个指向数组单个元素的指针,因此arr
和arr+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]
这个概念也可以扩展到三维数组,但这是每个初学者应该理解的最小值。如果我在概念上或语法上错了,请更正我。
答案 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
引用地址arr
,arr
的大小是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)]
。一旦你绕过它,它就会更有意义。
arr
和arr+1
不应该相邻,应该有4个字节的差异。究竟是什么结果?
答案 5 :(得分:0)
数组是character
,因此每个字段占用1个字节。 arr
和arr+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。