2
#include<stdio.h>

struct Book {
    char * name;
    int page;
};

void demo(struct Book bookArr[]);

int main(){
    struct Book bookArr[] = {{"c struct",1},{"c struct",2}};
    printf("bookArr address from main: %p\n",&bookArr);
    printf("bookArr[0] address from main: %p\n",&bookArr[0]);
    demo(bookArr);
    return 0;
}

void demo(struct Book bookArr[]){
    printf("bookArr address from demo: %p\n",&bookArr);
    printf("bookArr[0] address from demo: %p\n",&bookArr[0]);
}
The output: 
bookArr address from main: 0x1040bb350
bookArr[0] address from main: 0x1040bb350
bookArr address from demo: 0x1040bb328
bookArr[0] address from demo: 0x1040bb350
Program ended with exit code: 0

The bookArr in the demo copies the bookArr in main at startup, so I can understand why the bookArr addresses of the two functions are different, but I can't understand why both functions have the same bookArr[0] address. Wasn't the demo already assigned a full BookKarr? Are bookArr[0] and bookArr[1] both Pointers? But that's not the case

2
  • I have not understood the question What does this "Are bookArr[0] and bookArr[1] both Pointers?" mean? Commented Jun 16, 2021 at 19:14
  • I don't understand why these two functions have the same bookArr[0] address. Commented Jun 16, 2021 at 19:19

3 Answers 3

2

For starters consider a simple example:

#include <stdio.h>

void f( int *px )
{
    printf( "in f &( *px ) = %p\n", ( void * )&( *px ) );
    
}
int main(void) 
{
    int x = 10;
    
    printf( "in main &x    = %p\n", ( void * )&x );
    
    f( &x );
    
    return 0;
}

The program output might look like:

in main &x    = 0x7ffccc31de34
in f &( *px ) = 0x7ffccc31de34

That is the variable x is passed to the function f by reference through a pointer to it.

Dereferencing the pointer in the function *px you get a direct access to the memory where the variable x is stored. The variable x itself was not transferred to the function. It s a pointer to the variable that was transferred.

So using the expression &( *px ) or &( px[0] ) or just px you will get the address of the original variable x in main.

When you are passing an array then it is implicitly converted to pointer to its first element. On the other hand, a function parameter having an array type is also adjusted to the type pointer to the array element type.

That is this function declaration:

void demo(struct Book bookArr[]);

is equivalent to:

void demo(struct Book * bookArr);

So the array itself is not copied in the function. It is the pointer to its first element that is passed to the function.

So the value of the parameter bookArr gets the address of the first element of the array. In fact the parameter bookArr get the value of the expression book &bookArr[0] where bookArr declared in main. So in fact all elements of the array declared in main are passed to the function by reference because using the pointer arithmetic you can get the address of each element of the array. That is bookArr is the address of the first element of the array *the expression you can also write like &bookArr[0]), bookArr + 1 is the address of the second element of the array, and so on.

Pay attention to that in main in this call

 printf("bookArr address from main: %p\n",&bookArr);

the expression &bookArr does not have the type struct Book *. It has the type struct Book ( * )[2] because in main you have an array. On the other hand in the function demo bookarr has the type struct Book * (due to adjusting the parameter to pointer to the array element type) and the expression &bookArr has the type struct Book ** and yields the address of the parameter (local variable of the function).

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much! The explanation is very comprehensive, was taught
I tried to output sizeof(bookArr) in the demo, and the result was 8, which verified your explanation. Thank you very much
1

The bookArr in the main function is an array.

Most arrays in expressions are automatically converted to a pointer to their first element, but an operand of unary & operator is one of the exceptions of that.

Typically the place of an array and one of its first element will be the same address in the memory. (There are no extra space in the array before the first element.)

bookArr[0] and bookArr[1] are not pointers but structures (struct Book`).

2 Comments

‘bookArr[0] and bookArr[1] are not pointers but structures (struct Book`).’ , So, I can't understand why both functions have the same bookArr[0] address.
The addresses of bookArr[0] are same because they are looking at the same structure in the array.
0

There is, in fact, only a single Book array in existence, and both functions refer to the same array. However, each function accesses that array via a different local variable.

In either function, &bookArr is not the address where the array starts. It's the address of the local variable that holds the pointer to the start of the array.

If you were to print bookArr itself, which is a pointer in its own right, you'd see that both of them point to the same memory location.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.