-1

When I print the (size of the array/size of the the first element), I get the right answer, but when I do the same thing in the function, I get the size of the array to be four and the size of the first element of the array to be four hence the division is always one.

#include<stdio.h>
int sizer(int *); 

int main()
{
    int num;
    printf("Please an index: ");
    scanf("%d",&num);
    int array[num];
    int size = sizer(array); //function to calculate array length

    /*answer is always 4*/
    printf("%d\n", size); 

    /*answer is correct*/
    printf("%d\n", sizeof(array) / sizeof(array[0])); 

    return 0;
}

/*function to calculate array length*/
int sizer(int *array)
{
    return sizeof(array) / sizeof(array[0]);
}
  • 1
    The short answer: you can't pass arrays to functions, only pointers to their first element. Thus, the sizeof of any function's pointer parameter is always the size of the pointer. – Jens Aug 30 '15 at 14:23
  • Are you trying to dynamically allocate that array? Since `num` does not have a value known at compile time, this looks like bad code to me. Lookup dynamic memory allocation. – FreelanceConsultant Aug 30 '15 at 14:26
  • 1
    @user3728501 It's allowed in C99. https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html – Colonel Thirty Two Aug 30 '15 at 15:12
  • @ColonelThirtyTwo Fair enough - how does that work in terms of machine code? I assume there must be some sort of loop which does a "push" operation on the stack until the size required is reserved on the stack? – FreelanceConsultant Aug 30 '15 at 15:15
  • @user3728501 Just move the stack pointer `sizeof(T)*len` bytes up and use the resulting space as the array. – Colonel Thirty Two Aug 30 '15 at 15:16

2 Answers2

1

sizeof is not a function called at runtime, even though it looks like one. It is a feature of the compiler. It looks at a data object and replaces the sizeof() expression with a constant.

int arr[10];
int size = sizeof(arr)/sizeof(int);

This works because the compielr can see how big arr is. arr is a statically sized array here. Both sizeof expressions are replaced with the appropriate values.

int arr[10];
int size = sizer(arr);
....
int sizer(int array[]) {
    return (sizeof(array)/sizeof(int));
}

This doesn't work. In sizer, array looks like an array but arrays passed in as parameters are actually just pointers to the array type. So sizeof(array) is equivalent to sizeof(int *)

scanf("%d",&num);
int arr[num];
int size1 = sizeof(arr)/sizeof(int);
int size2 = sizer(arr);
....
int sizer(int array[]) {
    return (sizeof(array)/sizeof(int));
}

Here, size1 works but size2 doesn't. The creation of arr is actually allocated like this:

int arr_sizeof = sizeof(int)*num;
int *arr = alloca(arr_sizeof);

Then later on, sizeof(arr) is quietly replaced with arr_sizeof. But the compiler can only do this in the same scope that arr is created, because when arr is passed to sizer it's just converted to an int * again, so the size information is not carried over. sizer fails for thet same reason, arrays in function parameters are just passed along as simple pointers.

NovaDenizen
  • 5,089
  • 14
  • 28
  • You can pass the length of the array in arguments as well, e.g. (`size_t size(size_t len, int a[len])`, but the type in the function is still `int*`. So `sizeof` would still only return the size of the pointer. – Jason Aug 30 '15 at 15:37
0

When you pass an array to a function you are really just passing a pointer to the first element, so in the body of sizer, the parameter array is just a pointer to int. Your function correctly returns sizeof(int*)/sizeof(int) (which is 2 rather than 4 on my machine), though this is probably not what you want. There really isn't any way for a function in C to compute the length of a passed array, which is why it is standard in C to pass the number of elements in an array as one of the parameters in any function which takes an array parameter.

John Coleman
  • 51,337
  • 7
  • 54
  • 119