【问题标题】:Pointer to the Address of Element of an Array指向数组元素地址的指针
【发布时间】:2016-09-21 07:11:09
【问题描述】:
int s[4][2]= {
             {1234,56},
             {1212,33},
             {1434,80},
             {1312,78}
             };
int i,j;
for(i=0;i<=3;i++)
{
    printf("\n");
    for(j=0;j<=1;j++)
    {
        printf("%d  ",*(s[i]+j));
    }
}

输出显示为

1234,56
1212,33
1434,80
1312,78

我们知道*(&amp;Variable) 将打印变量的值但是当我们在上面的程序中实现相同的概念时......

int s[4][2]= {
             {1234,56},
             {1212,33},
             {1434,80},
             {1312,78}
             };
int i,j;
for(i=0;i<=3;i++)
{
    printf("\n");
    for(j=0;j<=1;j++)
    {
        printf("%d  ",*(&s[i]+j));
    }
}

输出显示数组中每个元素的地址。

为什么会这样? 为什么输出不等于数组元素的值??

【问题讨论】:

    标签: c arrays pointers multidimensional-array addressof


    【解决方案1】:

    请注意s 是一个二维数组,在某些情况下,数组名称会衰减为指向第一个元素的指针。

    这里,s[i] 是数组类型,两个ints 的数组。

    然后,引用C11,第 §6.3.2.1 章,

    除非它是sizeof 运算符、_Alignof 运算符或 一元 &amp; 运算符,或者是用于初始化数组的字符串文字,具有 type ''array of type'' 被转换成一个类型为 ''pointer to type'' 的表达式,它指向 到数组对象的初始元素并且不是左值。 [...]

    因此,

    • 在第一种情况下,

      *(s[i]+j)
      

      s[i]int [2] 类型,它衰减为int *,用于指针运算,产生另一个int *。取消引用后,您会得到一个int

    • 第二种情况,

      *(&s[i]+j)
      

      由于与上述相同的原因,在&amp;s[i]的情况下,s[i]不会衰减,并且类型是“指向int [2]的指针”并且指针运算在此基础上起作用。因此,在这种情况下,加法的结果也是“指向int [2] 的指针”,在最终取消引用之后,它变为int *,这是%d 的不匹配,这就是您的编译器报告的内容。

    【讨论】:

    • 感谢您的解释
    【解决方案2】:

    您的数组是二维的。所以,s[i] 是行i 的地址(即s[i]int * 类型),&amp;s[i] 是地址的地址(即int ** 类型)。当你在上面应用* 时,你会得到一个地址(即int *)。

    确实,运算符&amp;表示“地址”,*(&amp;x)表示x的值。

    【讨论】:

    • 谢谢,我认为所问的问题是准确的
    • "s[i] 的类型是 int *" NO. s[i] 属于 int [2] 类型,一种数组类型,在某些上下文中可以隐式转换为 int *。 “and &s[i] 是一个地址的地址(即 int ** 类型)”NO. &amp;s[i]int (*)[2] 类型,一个指向数组的类型。 “当你在上面应用 * 时,你会得到一个地址(即 int *)”同样,不。你会得到int [2],在某些情况下可以隐式转换为int *
    • @newacct 哈哈。好的。但我更喜欢简单地说(但不是 %100 准确)让初学者容易理解,而不是说准确而复杂的答案。此外,int [2]int * 之间的这种区别在某种程度上是“合乎逻辑的”,恕我直言,在这个问题的答案中不值得一提,因为@Kunal 在他的问题中谈到了地址。
    • @newacct 您可以看到答案比“真正准确”的答案更能满足 PO。
    【解决方案3】:

    第一种情况

    你的打印声明是这样的。

    printf("%d  ",*(s[i]+j));
    

    这里 s[i]+j 是地址。

    让我们考虑 i=0,j=1 ,第一个 i 循环,第二个 j 循环。

    这里 s[i] 将是值 1234 所在的地址。可以说是489000。 所以 s[i]+j ,这里 s[0]+1 将是值 56 所在的地址。假设它是 489004

    所以,*(s[i]+j),即;这里 *(s[0]+1) 将给出地址 489004 的值。即 56。 所以在这里它将打印值 1234、56、1212 等。

    第二种情况 您的打印声明是这样的。

    printf("%d  ",*(&s[i]+j));
    

    这里&s[i]+j是地址。

    让我们考虑 i=0,j=0 ,第一个 i 循环,第一个 j 循环。

    这里 s[i] 将是值 1234 所在的地址。 假设它是489000。 所以 &s[i] 将是地址 489000 所在的地址。 假设它是380000。 回忆一下指针的概念。

    所以 &s[i]+j 将是“地址 489000 所在的地址 + j”。 IE; 380000+j

    我们正在对我们得到的这个特定的“地址”应用一个操作符 * 的值。 *(&s[i]+j)。 于是就变成了, ['地址 489000 所在的地址' + j] 处的值。 值为 [380000 + j]。

    当 i=0,j=0 时,会打印 Value At[380000] ,即; 489000.

    因此它将打印存储值 1234、56、1212 等的地址。

    【讨论】:

    • @Kunal Verma :希望这会有用。
    • @Kunal Verma:不客气。如果您清楚概念,请为答案投票,以便其他人也可以检查。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    相关资源
    最近更新 更多