4

Running the following code will print out orld. What is happening here? What exactly does &(p[*(i + j)]) do?

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

int main()
{
    printf(&(p[*(i + j)]));
    return 0;
}
marktani
  • 7,578
  • 6
  • 37
  • 60
  • 7
    Hint: _pointer arithmetic_ – devnull Mar 10 '14 at 13:13
  • p is `char[]` and ur passing &p to printf. The start is given by expression `*(i+j) == 6` It will print the entire char array until it hits the escape character `\0`. If you want to print only the character at the location try `p[*(i+j)]` – DOOM Mar 10 '14 at 13:13
  • 1
    Is this an execise? I hope nobody writes such things in real life. – Jens Gustedt Mar 10 '14 at 13:13
  • 1
    Start from http://stackoverflow.com/questions/381542/with-c-arrays-why-is-it-the-case-that-a5-5a , which explains the inner-most part. – DCoder Mar 10 '14 at 13:15
  • @Jens: It is an exercice I stumbled on. – marktani Mar 10 '14 at 13:15
  • So then asking that question here is completely counter productive. Search the web / documentation / whatever to understand enough to solve it yourself. – Jens Gustedt Mar 10 '14 at 13:16
  • To the people voting for close: Could you please explain what is unclear? He has a perfectly clear question that can be answered. – Martin Thoma Mar 10 '14 at 20:29

6 Answers6

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

&(p[*(i + j)]) is evaluated as below:

here i is the base address of array i. Thus i+4 will be the address of the fifth element in the array i. *(i+j) will be equal to 6. P[6] will be o after W. &(p[*(i + j)]) would be equal to &p[6]. Thus in printf you are passing the address of o and the output would be orld.

Rahul
  • 3,479
  • 3
  • 16
  • 28
  • So printf(&p[6]) will print the content of array p until it hits \0? How is this mechanism called? – marktani Mar 10 '14 at 13:21
  • @mcwise yes it is. printf takes the address of string to be printed and it prints the string until it hits \0 – Rahul Mar 10 '14 at 13:23
  • 1
    @mcwise: see http://stackoverflow.com/questions/3332611/how-is-printf-statement-interpreted/ . – DCoder Mar 10 '14 at 13:39
3

Let's start off by learning these couple of facts:

1) Arrays are sequence of allocated memory locations. 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; 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.

3) asd[3], *(asd + 3) and 3[asd], all are the same; they all point to the content of the memory location that has the address asd + 3. The pointer type of the asd is important here, it determines how much bits/bytes to offset from the asd. As for int * asd, asd + 3 will advance 3 * sizeof ( int ) bytes ahead of the asd.

Now, with all this, let's examine what &( p[ *(i + j) ] ) really is:

    &( 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.

haccks
  • 104,019
  • 25
  • 176
  • 264
Utkan Gezer
  • 3,009
  • 2
  • 16
  • 29
  • Good explanation. +1. But you should remove the line `&( "HelloWorld"[6] )` and `"HelloWorld" + 6`. It is bit confusing to a newbie. – haccks Mar 10 '14 at 13:40
2

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
  • i is an array of 5 integers
  • j is an integer and has the value 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. 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

So this "slices" the array HelloWorld to orld. In Python you would write p[6:], in C you write &p[6].

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
1

Let's go by steps: *(i+j) it's the same as i[j], that is 6. p[6] is the value at p pointer plus 6.

The address of operator get the address of that character, thus a char*.

A char pointer pointing to the 6th character of p passed to the printf function print the text "orld".

wizard
  • 1,456
  • 1
  • 11
  • 20
1

&(p[*(i + j)]) leads to below expression which is address of p[6] being 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.

Sunil Bojanapally
  • 12,528
  • 4
  • 33
  • 46
0

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;
}
developer
  • 4,744
  • 7
  • 40
  • 55