我对2D阵列有点困惑。特别是使用公式 a[i][j] = *(*(a+i)+j)
在提出疑问之前,我想谈谈我对符号'*'
和'&'
的看法。我认为'&'
是一个运算符,它以“变量”作为操作数并给出“变量的地址”,而'*'
是将“变量地址”作为操作数并给出“变量”作为输出,所以/ p>
1.*(address)---->>(gives variable)
2.&(variable)---->>(gives address)
(请告诉我这个概念是否错误)
现在假设有一个二维数组“ a”,如下所示:
a[3][2]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}}
现在,我想使用该公式访问数组块的最后一个元素,即a[3][2]
。
第一个疑问
所以按公式:
a[3][2]=*(*(a+3)+2) // 1
我已阅读到a + 3给出了4rt行的第一个元素的地址,即&a[3][0]
。
但是我见过有人说写a等效于&a[0][0]
。因此代入方程式(1)
a[3][2] *(*(&a[0][0] +3)+2)
因此,在&a[0][0]
上加3表示对块a[1][0]
.....(在a[0][0]
前面的三个块)进行地址分配。因此,这里我们的(a + 3)已将我们指向&a[1][0]
,而不是&a[3][0]
。
第二个疑问
假设现在求值(a + 3)确实给了我a [3] [0]的地址(正确)。所以等式(1)现在变为
a[3][2]=*(*(&a[3][0])+2)
使用我的概念
*(address of variable)---->>(gives variable)
所以*(&a[3][0])= a[3][0]
。因此a [3] [0]应该是一个存储值10的变量。现在,我们有了a[3][2]=*(10+2)=*(12)
。但是,现在'*'
运算符需要地址作为输入,并且我们给出的r值不是地址,因此应该给出错误。
我知道我的概念中有很多错误,但是我是一个初学者,刚开始使用C语言作为我在编程领域的第一个话题,请帮帮我。
答案 0 :(得分:1)
我认为'&'是一个将变量作为操作数并给出该变量地址的运算符...
这不是很正确。我们应该澄清什么是“变量”。在C语言中,通常称为变量的是标识符和对象。标识符是我们用作名称的文本字符串。例如,在int xyz;
中,“ xyz”是标识符。对象是用于表示值的内存区域。因此,在int xyz;
中,对象是编译器在内存中保留的几个字节(通常是四个字节)。
&
运算符提供了将其应用于的对象(或函数)的地址。请注意,不必将其应用于变量,只需将其应用于任何对象(或函数)即可。因此,代替命名对象,它可以应用于某些计算对象(如&a[i+4]
)或字符串文字(&"abc"
)或复合文字(& (int []) {3, 4, 5}
)。>
…和'*'可逆地将变量的地址作为操作数,并将变量作为输出,
*
使用指向对象(或函数,在此不再讨论)的指针,并生成对象(具体来说,是指定该对象的左值)。该对象不必是命名变量的对象。它可以是数组元素,也可以是动态分配的对象或其他任何东西。
现在假设有一个二维数组“ a”,如下所示:
a [3] [2] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}}
这不是正确的数组定义,因为它没有元素类型,并且因为它说数组的维数是3和2,但是初始化程序列表显示的维数应该是4和3。让我们假设将其更正为:
int a[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
我已经读到a + 3给出了第四行的第一个元素的地址,即&a [3] [0]。
不完全是。在表达式a+3
中,a
指定一个数组。该数组会自动转换为指向其第一个元素的指针,因此它等效于&a[0]
。请注意,此表达式的类型是3 int
的数组-它是a
的子数组。当我们加3时,编译器将计数3个子数组,因此a+3
指向子数组编号3(从0开始编号)。因此a+3
等效于&a[3]
。
&a[3]
是第3个子数组的地址。这与&a[3][0]
是第3个子数组的元素号0的地址不同。尽管它们实际上指向了在内存中的同一位置,它们具有不同的类型,并且编译器将它们区别对待。
但是我看到有人说写a等同于&a [0] [0]。
那是不正确的。 a
等效于&a[0]
,它是指向a
第一个元素的指针。 a
的第一个元素本身是一个数组;它是a[0]
,而不是a[0][0]
。尽管&a[0]
和&a[0][0]
实际上可以指向内存中的相同位置,但是它们具有不同的类型,并且编译器将对它们进行不同的处理。
所以代入公式(1)
由于a
不等同于&a[0][0]
,因此不能用后者代替前者。
让我们回到您提到的公式:
a [i] [j] = *(*(a + i)+ j)
这是正确的。回想一下,a
会自动转换为&a[0]
。然后&a[0]+i
对i
个子数组进行计数,加法的结果等于&a[i]
。然后,在*(a+i)
中,我们应用*
运算符。这会将&a[i]
更改为*&a[i]
。由于&a[i]
指向a[i]
,所以*&a[i]
是a[i]
。
现在,我们已经确定*(a+i)
变成a[i]
,并且我们想知道*(a+i)+j
是什么。实际上,我们在问a[i]+j
是什么。因此,我们必须弄清楚此表达式中a[i]
会发生什么。
回想一下a[i]
是a
的子数组。因此它本身就是一个数组。在表达式中使用数组时,数组会自动转换为其第一个元素的地址(用作sizeof
或一元&
的操作数时除外)。因此a[i]
被转换为&a[i][0]
。然后,我们添加j
,生成&a[i][0] + j
。由于&a[i][0]
是指向int
的指针,因此编译器对j
int
进行计数并生成指向a[i][j]
的指针。也就是说,*(a+i)+j
的结果是&a[i][j]
。然后应用*
会产生*&a[i][j]
,即a[i][j]
。