c语言指针部分的法则

在进行知识点梳理时发现脱衣服法则:
即↓
数组方式改成指针方式a[2] 变成 (a+2)
a[2][3]变成 (a+2)[3]
再可以变成 ((a+2)+3)

感到有些无厘头,求再进一步讲解什么是脱衣服法则

基于Monster 组和GPT的调写:
脱衣服法则是一个用于将数组下标表达式转换为指针表达式的技巧。它的基本思想是将数组下标表达式中的数组名替换为对应的指针,并使用指针运算符来代替数组下标运算符。脱衣服法则的名称来自于将数组“脱掉”(即去掉数组名)的过程,类似于脱掉衣服。

假设有一个二维数组a,可以用脱衣服法则将a[2][3]转换为指针表达式。首先,将a[2]转换为指针表达式,即(a+2),然后用指针运算符[]访问该指针所指向的数组元素,即(a+2)[3]。由于指针运算符[]优先级高于指针运算符+,因此需要使用括号来确保正确的运算顺序。因此,脱衣服法则将a[2][3]转换为((a+2)+3)。

脱衣服法则对于理解指针和数组在内存中的存储方式以及它们之间的关系非常有帮助。它也有助于简化某些复杂的数组下标表达式,使代码更易于理解和维护。

方案来自 梦想橡皮擦 狂飙组基于 GPT 编写的 “程秘”


"脱衣服法则"(或称为"裤子下脱法则")是一种用于将多维数组的访问方式从数组下标转换为指针的方法,其基本思想是逐步"脱掉"每个维度的下标,直到剩下指针为止。

例如,对于一个二维数组a,可以将a[i][j]转换为*((a+i)+j),其中a+i是一个指向第i行的指针,(a+i)表示第i行的首元素,*(a+i)+j就是第i行的第j个元素。

同样的,对于一个三维数组a,可以将a[i][j][k]转换为*(((a+i)+j)+k),其中a+i是指向第i个二维数组的指针,(a+i)是第i个二维数组的首地址,(a+i)+j是第i个二维数组的第j行的首地址,*(a+i)+j+k是第i个二维数组的第j行第k个元素的地址。

这种方法可以使访问数组元素的效率更高,因为指针的运算速度通常比数组下标的运算速度更快。此外,使用指针访问数组元素也可以方便地进行指针运算和指针的传递,使得程序的表达更加简洁。

[] 这个运算符你可以看成是 解引用*() ;
举例: a[1] 等价于 *(a+1); a[0] 等价于 *(a+0) ; a[5] 等价于 (a+5); a是数组名字,代表的是数组首元素地址。a+5相当于找到数组的第五个元素的地址,在(a+5) 就是第5个元素的值。
二级数组也是一样的, a[2][3] = *(a+2)[3] , 也等于 ((a+2)+3) 。这里a也是数组首元素地址,和上面差不多的。

“脱衣服法则”(也称为“脱星号法则”)是C语言中指针和数组之间的一个重要转换法则,它可以使代码更加简洁清晰。该法则是指,将数组名改写成指针,并去掉对应位置的星号,从而实现指针和数组的等价转换。下面以二维数组为例,对“脱衣服法则”进行进一步解释。

假设有一个二维数组a[2][3],它可以看作一个由两个长度为3的一维数组组成的数组。如果要将a[1][2]的值改为10,可以使用以下语句:

a[1][2] = 10;

这里使用了数组的方式访问a[1][2]的值。使用指针的方式访问a[1][2]的值,可以先将a数组名改写成指向int类型的指针,然后使用下标访问第二行第三列的元素。这可以使用以下语句实现:

int *p = &a[0][0]; // 将a数组名改写成指针
*(p + 1 * 3 + 2) = 10; // 访问第二行第三列的元素,并将其值改为10

这里的指针p指向a[0][0],即二维数组的第一个元素,使用*(p + 1 * 3 + 2)就可以访问第二行第三列的元素。这里1 * 3是计算第二行的偏移量,+ 2是计算第三列的偏移量。

在使用“脱衣服法则”后,以上语句可以更加简洁地写成:

int *p = a[0]; // 将a数组名改写成指针,等价于p = &a[0][0]
*(p + 1 * 3 + 2) = 10; // 访问第二行第三列的元素,并将其值改为10

这里的a[0]表示a数组的第一个一维数组,即&a[0][0]的地址,也就是p指针的值。这种方式可以更加简洁地实现指针和数组之间的转换。