简体   繁体   English

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

[英]What exactly does &(p[*(i + j)]) do?

Running the following code will print out orld . 运行以下代码将打印出orld What is happening here? 这里发生了什么? What exactly does &(p[*(i + j)]) do? &(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;
}
char p[] = "HelloWorld";
int i[] = {2,1,3,5,6}, j = 4;

&(p[*(i + j)]) is evaluated as below: &(p[*(i + j)])评估如下:

here i is the base address of array i . 这里iarray ibase address Thus i+4 will be the address of the fifth element in the array i . 因此i+4将是array i fifth elementaddress *(i+j) will be equal to 6 . *(i+j)将等于6 P[6] will be o after W . P[6]oW &(p[*(i + j)]) would be equal to &p[6] . &(p[*(i + j)]) 等于 &p[6] Thus in printf you are passing the address of o and the output would be orld . 因此,在printf您传递的address of oaddress of o 输出将是orld

Let's start off by learning these couple of facts: 让我们从了解这几个事实开始:

1) Arrays are sequence of allocated memory locations. 1) 数组是分配的存储位置序列。 The array label itself, is the address of the memory location of the very first element of the sequence. 数组标签本身是序列的第一个元素的内存位置的地址。 Example: 例:

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) When the programme encounters a string literal, that is, anything inside double quotes, like "HelloWorld" in your example, it fills some memory location with those characters, and then one more character, '\\0' as a mark of end, so that programme may know when to stop; 2)当程序遇到一个字符串文字时,即双引号内的任何内容,例如你的例子中的"HelloWorld" ,它用这些字符填充一些内存位置,然后再添加一个字符, '\\0'作为结束标记,以便程序可以知道何时停止; then, it returns the memory location of the first character. 然后,它返回第一个字符的内存位置。 So in other words, "HelloWorld" alone creates an array and returns the label of that array. 换句话说, "HelloWorld"单独创建一个数组并返回该数组的标签。

3) asd[3] , *(asd + 3) and 3[asd] , all are the same; 3) asd[3]*(asd + 3)3[asd] ,都是一样的; they all point to the content of the memory location that has the address asd + 3 . 它们都指向具有地址asd + 3的内存位置的内容。 The pointer type of the asd is important here, it determines how much bits/bytes to offset from the asd . asd的指针类型在这里很重要,它确定从asd偏移多少位/字节。 As for int * asd , asd + 3 will advance 3 * sizeof ( int ) bytes ahead of the asd . 至于int * asdasd + 3将在asd之前提前3 * sizeof ( int )字节。

Now, with all this, let's examine what &( p[ *(i + j) ] ) really is: 现在,有了这一切,让我们来看看&( 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'

Then this is pushed into the printf as the const char * argument, which prints 'o' , then 'r' , then 'l' , then 'd' , and then encounters the '\\0' , thus understands that the string is over and stops there. 然后将其作为const char *参数推入printf ,打印'o' ,然后'r' ,然后'l' ,然后'd' ,然后遇到'\\0' ,从而理解字符串是结束并停在那里。

I'll try to simplify it step by step 我会尝试逐步简化它

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

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

The first three lines are obvious: 前三行显而易见:

  • p is an array of 10 characters p是一个包含10个字符的数组
  • i is an array of 5 integers i是一个5个整数的数组
  • j is an integer and has the value 4 j是一个整数,其值为4

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

is the same as 是相同的

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

is the same as 是相同的

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

is the same as 是相同的

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

Now you have to know what *address gives you the value that is in address . 现在,你必须知道什么*address给你,是在价值address So: 所以:

printf(&(p[6]));

Now that's the point where I guess you were struggling. 现在这就是我猜你正在挣扎的地步。 You have to know: 你必须知道:

  • arrays are basically nothing else than a part in memory that is continuous. 数组基本上只是内存中连续的一部分。 It is specified by it's starting address. 它由起始地址指定。
  • &something gives you the address of something &something为您提供something地址

So this "slices" the array HelloWorld to orld . 所以这将“ HelloWorld ”数组“切片”到orld In Python you would write p[6:] , in C you write &p[6] . 在Python中,您可以编写p[6:] ,在C中编写&p[6]

Let's go by steps: *(i+j) it's the same as i[j] , that is 6 . 让我们一步一步: *(i+j)它与i[j]相同,即6 p[6] is the value at p pointer plus 6. p[6]是p指针加上6的值。

The address of operator get the address of that character, thus a char* . 运算符的地址获取该字符的地址,因此为char*

A char pointer pointing to the 6th character of p passed to the printf function print the text "orld". 指向传递给printf函数的p的第6个字符的char指针打印文本“orld”。

&(p[*(i + j)]) leads to below expression which is address of p[6] being j = 4 . &(p[*(i + j)])导致下面的表达式,即p[6]地址为j = 4

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

Yes you can print using printf without format %s specifier since it takes strings as arguments. 是的,您可以使用printf进行打印而不使用格式%s说明符,因为它将字符串作为参数。

Read comments for explanation 阅读评论以获得解释

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM