4

This is the code below to illustrate the issue:

#include <stdio.h>

void func(int arr[]);

int main() {
    int arr[10];
    int n = *(&arr + 1) - arr;
    printf("%d\n", n);
    func(arr);
    return 0;
}

void func(int arr[]) {
    int n = *(&arr + 1) - arr;
    printf("%d\n", n);
}

Output of the above code is:

10
268435906
msc
  • 33,420
  • 29
  • 119
  • 214
Abhishek Ghosh
  • 597
  • 7
  • 18
  • 2
    `int n=*(&arr+1)-arr;`..are you sure? – Sourav Ghosh Jun 27 '18 at 06:48
  • 1
    @SouravGhosh No that's correct (in that it will most likely work even though it's technically invalid). `&arr + 1` is a pointer to an array, dereference it (i.e. `*(&arr + 1)`) and you get an array, which then decays to a pointer to its first element (which will be pointing to one element beyond the end of `arr`, i.e. effectively a pointer to `arr[10]`). – Some programmer dude Jun 27 '18 at 07:04
  • @JensGustedt: this question is not an exact duplicate, it uses a different expression to compute the array size. – chqrlie Jun 27 '18 at 11:21

3 Answers3

7

Despite the syntax used for its definition void func(int arr[]), function func receives a pointer to the first element of the array. The definition is clearer as void func(int *arr).

The expression *(&arr+1)-arr evaluates at compile time to the number of elements of an array only if arr is defined as an array. If arr is a pointer, it dereferences memory after the pointer and subtracts the pointer value, which is meaningless and in most circumstances has undefined behavior.

A more common (and more readable) expression to get the number of element of an array is

n = sizeof(arr) / sizeof(*arr);

If arr is an array, dividing its size in bytes by the size of an element in bytes produces the number of elements. The expression is evaluated at compile time, no runtime overhead. If arr is a pointer, dividing its size by the size of the type it points to is defined, but useless, just like your expression.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
5

When declaring an array argument in a function, it's not an array at all, instead it's a pointer.

The declaration

void funct(int arr[]);

is actually equal to

void funct(int *arr);

And that's the difference between the results you see. In the main function &arr is a pointer to the array, but in func the expression &arr is a pointer to the pointer variable. Those two pointers are very different.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

Whenever arrays are passed as the arguments to functions, they will decay into pointers in the function parameters.

C FAQ :

Since arrays decay immediately into pointers, an array is never actually passed to a function. You can pretend that a function receives an array as a parameter, and illustrate it by declaring the corresponding parameter as an array:

void f(char a[]) { ... }

The name of the array arr is decayed into the pointer to the first element of the array by the compiler. As a result, dereferencing the pointer yields the value stored at the first location of an array.

msc
  • 33,420
  • 29
  • 119
  • 214