1
#include <stdio.h>
int avg(int []);
void main(){
    int average;

    int marks[5]={10,15,20,30,45};
    printf("%d\n",sizeof(marks)); // answer is 20(as expected)
    avg(marks);

}
int avg(int marks[]){
    int sum=0;
    printf("%d\n",sizeof(marks)); // answer is 8(why???)
}

In this code, I was trying to print the sizeof the integer pointer marks. When I print the sizeof the marks inside the main method it gives 20 as the result as we expected. But the same object passes to the avg function and prints the sizeof marks it shows the result as 8. I couldn't understand why that was happening. Can anyone please clarify this?

Any help would be appreciated.

risni
  • 19
  • 4
  • 4
    As an argument `int marks[]` is really `int *marks`. And the size of a pointer is the size of the actual pointer itself, not what it might be pointing to. You can't pass arrays directly as arguments to functions. If you want to pass an array to a function, you should also pass the array size as argument as well. – Some programmer dude Oct 18 '22 at 13:30
  • 1
    Also note that the result type of the `sizeof` operator is a `size_t`. And the correct `printf` format to print a `size_t` is `%zu`. The format `%d` is for `int` only. Mismatching format specifier and argument type leads to *undefined behavior*. Modern compilers can warn you about this, and if you didn't get a warning then you need to enable more (use `-Wall -Wextra` for GCC and Clang, `/W4` for MSVC), and treat them as errors that *must* be fixed (and simple casting is almost *never* the proper fix). – Some programmer dude Oct 18 '22 at 13:32

2 Answers2

2

It is size of the int*, which is 8 on your system.

wocsom
  • 21
  • 2
2

In the C programming language, arrays "decay" into pointers when passed to functions.

This means that in the scope where an array is declared, sizeof will be able to tell you how many bytes it takes up, but once it is passed to another function, sizeof can only tell you the size of a pointer to the type of the array. Effectively, when an array is passed as a parameter, you lose all length-of-array related information. All that is preserved is the memory-address where the array starts, and its type, so in your case, sizeof marks in main() is equivalent to sizeof(int[5]) and sizeof marks in avg() is equivalent to sizeof(int*).

The consequences of this are that if you are going to be passing arrays of different lengths to a function, then you either have to send a separate length parameter, or give the function some way to infer the length of the array.

For instance, C strings are implemented as arrays of char, such that the last character of the array is the null-terminator byte, '\0'. This allows a function that expects a C-standard string parameter to keep reading byte after byte from the string without stopping until it finds the '\0', but this is controversial, as it is a rather significant source of bugs and security concerns, because if this assumption fails, and there is no '\0' at the end of the string, then the function could very well blindly access memory it has no business messing with.

If you need to pass an array pointer to a function and preserve its length, the best (or perhaps least controversial) solution is to pass the length along with the array, so int avg(int marks[],int numMarks); might be a function prototype that will serve your purposes. You could implement a system, where there is a value of int that is an invalid mark to be averaged, and use it to mark the end of the array, but this is likely a more difficult solution to implement safely.

Willis Hershey
  • 1,520
  • 4
  • 22