&(p [*(i + j)])究竟做了什么?

时间:2014-03-10 13:09:55

标签: c

运行以下代码将打印出orld。这里发生了什么? &(p[*(i + j)])究竟做了什么?

#include <stdio.h>
char p[] = "HelloWorld";
int i[] = {2,1,3,5,6}, j = 4;

int main()
{
    printf(&(p[*(i + j)]));
    return 0;
}

6 个答案:

答案 0 :(得分:3)

char p[] = "HelloWorld";
int i[] = {2,1,3,5,6}, j = 4;

&(p[*(i + j)])评估如下:

此处ibase address的{​​{1}}。因此array i将是i+4address的{​​{1}}。 fifth element将等于array i。在*(i+j)之后,6将为P[6]o与<{1}} 相等。因此,在W中,您传递的是&(p[*(i + j)]),而输出将是&p[6]

答案 1 :(得分:3)

让我们从学习这几个事实开始:

1) 数组是已分配内存位置的序列。数组标签本身是序列的第一个元素的内存位置的地址。例如:

int asd[5] = { 11, 12, 13, 14, 15 };    // <-- this is an array

/* the following is what it looks like in the memory:
11  12  13  14  15

the value of, for example, asd[4] is 15
the value of asd itself is the memory address of asd[0], the very first element
so the following is true:
asd == &asd[0]  */

2)当程序遇到字符串文字时,即双引号内的任何内容,例如示例中的"HelloWorld",它会用这些字符填充一些内存位置,然后一个更多字符,'\0'作为结束标记,以便程序可以知道何时停止;然后,它返回第一个字符的内存位置。换句话说,"HelloWorld"单独创建一个数组并返回该数组的标签。

3) asd[3]*(asd + 3)3[asd],都是一样的;它们都指向具有地址asd + 3的内存位置的内容。 asd的指针类型在这里很重要,它确定从asd偏移多少位/字节。对于int * asdasd + 3将在3 * sizeof ( int )之前提前asd个字节。

现在,有了这一切,让我们来看看&( p[ *(i + j) ] )到底是什么:

    &( p[ *( i + j ) ] )
    &( p[ *( i + 4 ) ] )
    &( p[    i[4]    ] )
    &( p[      6     ] )    // This will return the address of `7th` element to the printf. 
     ( p      +      6 )    // A pointer to second 'o'

然后将其作为printf参数推入const char *,其中'o',然后是'r',然后是'l',然后是{{1}然后遇到'd',从而理解字符串结束并停在那里。

答案 2 :(得分:2)

我会尝试逐步简化它

#include <stdio.h>
char p[] = "HelloWorld";
int i[] = {2,1,3,5,6}, j = 4;

int main()
{
    printf(&(p[*(i + j)]));
    return 0;
}

前三行显而易见:

  • p是一个包含10个字符的数组
  • i是一个包含5个整数的数组
  • j是一个整数,其值为4

printf(&(p[*(i + j)]));

相同

printf(&(p[*(i + 4)]));

相同

printf(&(p[*([adress of first element of i] + 4)]));

相同

printf(&(p[*([adress of fourth element of i])]));

现在您必须知道*address为您提供address中的值。所以:

printf(&(p[6]));

现在这就是我猜你正在挣扎的地方。你必须知道:

  • 数组基本上没什么 而不是记忆中连续的一部分。它由起始地址指定。
  • &something为您提供something
  • 的地址

所以这会将数组HelloWorld“切片”到orld。在Python中,您可以编写p[6:],在C中编写&p[6]

答案 3 :(得分:1)

让我们一步一步:*(i+j)它与i[j]相同,即6p[6]是p指针加上6的值。

运算符的地址获取该字符的地址,即char*

指向传递给printf函数的p的第6个字符的char指针打印文本“orld”。

答案 4 :(得分:1)

&(p[*(i + j)])会导致以下表达式,p[6]的地址为j = 4

&(p[*(i + j)]) == &(p[(i[j])]) == &(p[(i[4])]) == &(p[6]) == &p[6]

是的,您可以使用printf打印而不使用格式%s说明符,因为它将字符串作为参数。

答案 5 :(得分:0)

阅读评论以获取解释

#include <stdio.h>
char p[] = "HelloWorld";
int i[] = {2,1,3,5,6}, j = 4;

int main()
{
    printf(&(p[*(i + j)])); //*(i+j) = i[j] => i[4]= 6
    // &(p[*(i + j)]) => place the pointer in memory block that his address p[6]
    // so printf print the string starting from the p[6] ie from 'o' => orld
    return 0;
}