0
void f(int a[]);

int main() {
    int a[11];
    printf("1.%x  ", &a);
    f(a);
}

void f(int a[]) {
    printf("2.%x    ", &a);
}

Output:

1.e0de4940  2.e0de4928  

But the outputs will be the same when & are deleted. And why the difference is 12 no matter what the size of the array is?

Chris
  • 26,361
  • 5
  • 21
  • 42
Kopear
  • 11
  • 1
  • 2
    Are you aware of the concept of a copy? I.e. looks the same but is something different and somewhere else? – Yunnosch Dec 13 '21 at 19:42
  • You're trying to understand inner workings of the language, which are depending heavily on the compiler and the platform you are working on. Basically, you should not worry about these things, as they are not important. There will be a time when you understand them anyway. ;-) – DevSolar Dec 13 '21 at 19:42
  • 2
    C is call-by-value. You are passing a copy of the pointer to your array, so you are printing the location of the copy. – stark Dec 13 '21 at 19:43
  • 1
    `a` in `f` is a copy (ie allocated in different memory) of a pointer to `a`, so when you do `&a` you're seeing a different value. – Brady Dean Dec 13 '21 at 19:44
  • 1
    If you attempt to compile this program with warnings enabled and treated as errors, you will see this code produces 2 errors and refuses to be compiled. So always compile your programs that way, that would have pointed you in the right direction or at least have provided a hint. – Cheatah Dec 13 '21 at 20:19
  • @Cheatah: The warnings about wrong conversion specifiers would not have provided any information about why the addresses are different, which is what this question is about. – Eric Postpischil Dec 13 '21 at 20:39

6 Answers6

2

In main the call of printf

int a[11];
printf("1.%x  ",&a);

where you need to use the conversion specifier %p outputs the address of the array a.

Within the function f this call of printf outputs the address of the local variable (parameter) a of the function

printf("2.%x    ", &a);

As the array and the parameter a of the type int * occupy different extents of memory then their addresses are different.

Pay attention to that the parameter a gets the address of the first element of the array a declared in main. So the address stored in the parameter a is the same as the address of the array a in main. That is your could write

void f(int a[]);

int main() {
    int a[11];
    printf("1.%p  ", ( void * )&a);
    f(a);
}

void f(int a[]) {
    printf("2.%p    ", ( void * )a);
}

and as result you would get identical outputs.

You can simplify the code to make it easy to understand what is under the hood.

Consider the following code snippet

int a[11];
int *p = a;

as you see the two variables a and p occupy separate extents of memory. So these calls of printf yield different results

printf( "%p\n", &a );
printf( "%p\n", &p );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

int a[] is syntactically the same as int* a both of them are pointers to integers (also known as int arrays). Hence the correct way is without &

void f(int a[]){
    printf("2.%x    ", a);
}
int main() {
    int a[11];
    printf("1.%x  ",a);
    f(a);
}

But the outputs will be the same when & are deleted. And why the difference is 12 no matter what the size of the array is?

Initially, you have & which first prints the address of int a[11]. Then the address of that array is passed to f() where it makes a different pointer that also points to the same address. However, those are two different pointers, hence when you print the addresses of the actual pointers they are obviously different no matter where they point.

The difference of 12(which is actually 24 since the numbers are in hex) is arbitrary, it just tells you that those two pointers are stored in addresses that are 24 bytes away from each other

0

In main, a is an array, and &a is the address where that array is stored. When main calls f, the a in f(a) is automatically converted to the address of the first element of a, and that address is passed to f.

In f, a is a parameter, and &a is the address where that parameter is stored. The value of the parameter a is set to the valued passed in the function call, but &a is the address of the parameter, which is a copy of the value. It is not the original a in main.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

In your program there's an only on small mistake in function f(int a[])

void f(int a[]) {
        printf("2.%x    ", &a);
}

Function f returns the address of an argument to a function, not an address that it points to.

Since mastering pointers in C is understanding one of the essential aspects of, not only of C language itself, but machine architecture and basics of CPU/memory functionality.

So, making errors in pointer arithmetic and searching/debugging them can drive even experienced C programmer mad, it's no surprise that they are harnessed in C++ with static_cast, dynamic_cast keywords and completely removed (hidden, that is..) in computer languages that followed them after.

So, I went a little further and reworked your code explaining that error better.

#include <stdio.h>

void  f(int b[]) {
printf("\n func call. print address:    %x", &b);  }
void f2(int b[]) {
printf("\n func call. print address(2): %x",  b);  }

int main()
{
  int *j, a[11];

     j = a;   // load address of 'a' array to int pointer 'j'
              // pointer 'j'
              //   j  = address of an array 'a'
              //  &j  = address of 'j' !!
          
     *j = 1;  // value of any 'int' that 'j'
              // points to is 1,so the value              
              // of a[0]= 1 

// ______ print values of 'j', 'a' ______
    // value is from address 'a'
    printf("\n1.) value of number (j)= %d",   *j);
    // int value of address 'a'
    printf("\n1.) value of number (a)= %d",  a[0]);

// ______ print addresses of 'j', 'a' ______
    // address of int variable 'j' that 
    // holds pointer to 'a'
    printf("\n\n2.) addr of number (j)= %x", &j);
    // address of 'a' array
    printf("\n2.) addr of number (a)= %x",   &a);
      
// ______ all of following adressess are the same ______
    // actual pointer (points to 'a' now)
    printf("\n\n3.) addr of 'j'   = %x",     j);
    // address od an array 'a'
    printf("\n3.) addr of 'a'   = %x",       a);
    // address of first int member in array a
    printf("\n3.) addr of 'a[0]'= %x\n", &a[0]);
      
    // ______ print them from function ______ (yours) ..
       f(&j); f(a);    // outputs an address of an argument passed to a function !!!     
          
    // ______ print them from function ______ (changed) ..
       f2(&j); f2(a);  // outputs an address that an argument points to !! 
                          // (holds address of)

      return 0;
  }

That int b[] in functions f and f2 are written purposely instead of int a[] so that is clear that argument is a copy of a variable pushed on stack - not an actual variable a.

Program outputs:

1.) value of number (j)= 1

1.) value of number (a)= 1

2.) addr of number (j)= 5f826328
2.) addr of number (a)= 5f826330

3.) addr of 'j'   = 5f826330
3.) addr of 'a'   = 5f826330
3.) addr of 'a[0]'= 5f826330

 func call. print address:    5f826308
 func call. print address:    5f826308
 func call. print address(2): 5f826328
 func call. print address(2): 5f826330
0

The reason is that main() and f() put the local parameter a in different places in memory, as at some point, both main() and f() are in the middle of their execution and, as both parameters are local to their respective function they are defined in, they are indeed different variables (despite their name is the same)

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
-1

When you write int a[], you refer to a pointer because arrays are pointers. To refer to where a points to, you simply write a. When you write &a, you are referring to the memory address of the pointer itself. The memory address of the pointer itself is different, because you are passing pointers (the memory adresses themselves) by value, meaning that they have a copy in each function.

Chris
  • 26,361
  • 5
  • 21
  • 42
  • 3
    *"arrays are pointers"* - arrays are arrays, however the name of an array can decay into a pointer. See [1](https://stackoverflow.com/q/1461432/3889449), [2](https://stackoverflow.com/q/17752978/3889449). – Marco Bonelli Dec 13 '21 at 19:49