c语言 - 2D 数组中 (arry+i) 和 *(arry+i) 之间的混淆



我对这两个表达式有点困惑:(arry+i)*(arry+i)在二维数组中,两个表达式都给出相同的输出,即数组第 i 个元素的地址。

为什么会这样,*(arry+i)不应该指出第 i 个元素的值而不是第 i 个地址。

main() {
int arry[3][4] = { 1, 2, 3, 4,
4, 3, 2, 8,
7, 8, 9, 0
};
printf("%un", arry + 1);
printf("%un", *(arry + 1));
};

输出结果为:

2346225936 2346225936

正如我所期望的那样:

2346225936 四

如果你有一个二维数组声明如下

T a[M][N];

其中,当表达式( a + i )具有T( * )[N]类型并指向数组的第 i 个"行"时,T是某种类型。

表达式*( a + i )(即取消引用上面所示类型的指针)生成指向的"行"的左值,该值是类型T[N]的数组。在表达式中使用,数组指示符被转换为指向其第一个元素的指针。在这种情况下,数组将转换为类型T *

因此,T ( * )[N]T *类型的两个指针都指向容纳第 i 个"行"的相同内存范围的开头。也就是说,指针的值彼此相等,但指针本身具有不同的类型。

造成混淆的原因确实有多种:

  • arry定义为 3 个数组的数组,每个数组 4 个int。初始值设定项的可读性更强,如下所示:

    int arry[3][4] = {
    { 1, 2, 3, 4 },
    { 4, 3, 2, 8 },
    { 7, 8, 9, 0 }
    };
    

arry是此 2D 数组的名称,它不同于指向数组的指针。它的类型是int[3][4].导致混淆的原因是数组自动转换为指向其第一个元素的指针,每当它们在表达式中使用或作为函数参数传递时,都会隐式发生。(此规则的极少数例外:数组用作sizeof()_Alignof()的参数时不会转换。

  • arry + 1是这种转换的一个例子:arry被隐式转换为指向其第一个元素的指针,&(arry[0]),该元素的类型为int (*)[4],指向 4 个整数数组的指针。向其添加1会提供一个指向 2D 数组下一个元素的指针,&(arry[1])具有相同类型的int (*)[4]。若要打印此指针的值,应使用%p并将表达式转换为指向void的指针:

    printf("%pn", (void *)(arry + 1));
    

%u需要一个unsigned int,它可能具有不同的表示和参数传递约定,从而导致您的代码具有未定义的行为。

  • 取消引用上述指针,*(arry + 1)生成一个类型为int [4]的 L 值,该值是arry + 1指向的 4 个整数数组(作为&(arry[1])更具可读性。如果int的大小为4字节,此数组可用作sizeof和生成16的参数,但将其传递给printf会导致它转换为指向其第一个元素&(arry[1][0])的指针。同样,您应该使用不同的语法来打印此地址:

    printf("%pn", (void *)(*(arry + 1)));
    

    输出是相同的,因为数组及其第一个元素具有相同的地址,就像街道及其第一所房子具有相同的 GPS 坐标一样。

这是一个修改后的程序:

#include <stdio.h>
int main() {
int arry[3][4] = {
{ 1, 2, 3, 4 },
{ 4, 3, 2, 8 },
{ 7, 8, 9, 0 }
};
printf("              arry -> %-16p %sn", (void *)(arry), "the address of the 2D array");
printf("      sizeof(arry) -> %-16zu %sn", sizeof(arry), "the size of the 2D array");
printf("            arry+0 -> %-16p %sn", (void *)(arry+0), "the value of a pointer to row 0");
printf("    sizeof(arry+0) -> %-16zu %sn", sizeof(arry+0), "the size of a pointer to row 0");
printf("         *(arry+0) -> %-16p %sn", (void *)(*(arry+0)), "the address of row 0");
printf(" sizeof(*(arry+0)) -> %-16zu %sn", sizeof(*(arry+0)), "the size of row 0");
printf("           arry[0] -> %-16p %sn", (void *)(arry[0]), "the address of row 0");
printf("   sizeof(arry[0]) -> %-16zu %sn", sizeof(arry[0]), "the size of row 0");
printf("       &arry[0][0] -> %-16p %sn", (void *)(&arry[0][0]), "the value of a pointer to row 0, col 0");
printf("sizeof(arry[0][0]) -> %-16zu %sn", sizeof(arry[0][0]), "the size of the array element at 0,0");
printf("        arry[0][0] -> %-16d %sn", arry[0][0], "the value of the array element at 0,0");
printf("n");
printf("            arry+1 -> %-16p %sn", (void *)(arry+1), "the value of a pointer to row 1");
printf("    sizeof(arry+1) -> %-16zu %sn", sizeof(arry+1), "the size of a pointer to row 1");
printf("         *(arry+1) -> %-16p %sn", (void *)(*(arry+1)), "the address of row 1");
printf(" sizeof(*(arry+1)) -> %-16zu %sn", sizeof(*(arry+1)), "the size of row 1");
printf("           arry[1] -> %-16p %sn", (void *)(arry[1]), "the address of row 1");
printf("   sizeof(arry[1]) -> %-16zu %sn", sizeof(arry[1]), "the size of row 1");
printf("       &arry[1][0] -> %-16p %sn", (void *)(&arry[1][0]), "the value of a pointer to row 1, col 0");
printf("sizeof(arry[1][0]) -> %-16zu %sn", sizeof(arry[1][0]), "the size of the array element at 1,0");
printf("        arry[1][0] -> %-16d %sn", arry[1][0], "the value of the array element at 1,0");
return 0;
}

输出:

arry -> 0x7fff512997c0 2D 数组的地址 sizeof(arry) -> 48 2D 数组的大小 arry+0 -> 0x7fff512997c0指向第 0 行的指针的值 sizeof(arry+0) -> 8 指向第 0 行的指针的大小  *(arry+0) -> 0x7fff512997c0第 0 行的地址  sizeof(*(arry+0)) -> 16 行 0 的大小  arry[0] -> 0x7fff512997c0第 0 行的地址  大小(Arry[0]) -> 16 行 0 的大小  &arry[0][0] -> 0x7fff512997c0指向第 0 行、列 0 的指针的值 sizeof(arry[0][0]) -> 4 数组元素的大小为 0,0 arry[0][0] -> 1 数组元素的值为 0,0 arry+1 -> 0x7fff512997d0指向第 1 行的指针的值 sizeof(arry+1) -> 8 指向第 1 行的指针的大小  *(arry+1) -> 0x7fff512997d0第 1 行的地址  sizeof(*(arry+1)) -> 16 第 1 行的大小  Arry[1] -> 0x7fff512997d0第 1 行的地址  sizeof(arry[1]) -> 16 第 1 行的大小  &arry[1][0] -> 0x7fff512997d0指向第 1 行 col 0 的指针的值 sizeof(arry[1][0]) -> 4 数组元素的大小为 1,0 arry[1][0] -> 4 数组元素的值为 1,0

如您所见,arryarry[0]arry[0][0]的地址是相同的,指针的值是相同的,&arry&arry[0]&arry[0][0]

相关内容

  • 没有找到相关文章

最新更新