0

I read in the K&R C book that when we pass an array to a function, the address of the array (a pointer containing the address of the first element of the array) is passed to the function, therefore making it seem like a pass-by-reference (although there is no such real mechanism in C)

However, the below doesn't make sense to me then -

void test(char arr[10]) {
    arr[2] = 'a';
 }

 main() {
     char arr[5] = "hello";
     test(arr);
     printf("%s", arr);
     return 0;
 }

This gives me healo as expected.

But does that mean that this is how this is evaluated?

The "char arr[]" argument getting assigned the pointer to the actual array? How does that work?

char arr[10] = &arr[0] 

doesn't make sense to me!

RubyR
  • 79
  • 5
  • 1
    I don't see a contradiction. *"making it seem like a pass-by-reference"* - meaning that you *can* modify it and have the result visible outside the function. – Eugene Sh. Jan 08 '19 at 19:59
  • Yes a a copy of the address of the array is given as parameter. Yes, via this address, you do change the original array. What is unclear? – Yunnosch Jan 08 '19 at 20:00
  • arrays decay to pointers in may situations and one of it is when passing it to a function, so `test(arr);` is basicly the same as `test(&arr[0]);`. – Osiris Jan 08 '19 at 20:00
  • What I am confused about is this: I've always thought of it this way - that when we pass arguments to a function, the function's parameter in its definition and the actual argument while calling a function get equated. So when we say that we have `char arr[]` in the func definition but pass `&arr[0]`, I am unable to understand how those two get equated – RubyR Jan 08 '19 at 20:02
  • It is a special case for functions. When you specify an array as a function parameter, the C language treats the parameter as a pointer type, not an array type. – jxh Jan 08 '19 at 20:04
  • @user3655977 you give an array in argument, in that case its address is given, it is not copied – bruno Jan 08 '19 at 20:04
  • Bruno, my confusion is regarding how we actually equate the array defined in the function signature and the address that is passed from the function call. They two seem to be incompatible. @jxh is I think understanding what my confusion is – RubyR Jan 08 '19 at 20:07
  • @user3655977 `void test(char arr[])` and `void test(char *arr);` is the same, there is no difference. – Osiris Jan 08 '19 at 20:09
  • Even if I defined it as `void test(char arr[10])`, would it still ignore the 10 and consider it as just a char pointer? Wouldn't that mean loss of information (the value 10)? @Osiris – RubyR Jan 08 '19 at 20:11
  • @user3655977 Yes `arr` is then still of type `char *`. Giving dimensions to an array parameter does only make sense in the multi dimensional case. – Osiris Jan 08 '19 at 20:13
  • Alright, thanks a lot @Osiris – RubyR Jan 08 '19 at 20:16
  • user3655977 Re: [unable to understand how those two get equated](https://stackoverflow.com/questions/54098883/when-we-pass-an-array-to-a-function-how-does-the-copy-work#comment95030602_54098883). Think of it as 3 things. The argument given `main_arr` of type `int [10]`, the converted argument passed `&main_arr[0]` of type `char *` and the parameter received `char test_arr[10]` of type `char *`. – chux - Reinstate Monica Jan 08 '19 at 20:23

1 Answers1

0

in test the parameter arr receive the address of the argument because it is an array, not a copy, so you modify the value of the arr in main (it was more practical to not use the same name in test and main :-) )

void test(char arr[]) and void test(int * arr) are two ways to write the same thing

to call test(arr) and test(&arr[0]) are also two ways to write the same thing

bruno
  • 31,755
  • 7
  • 21
  • 36
  • my confusion is regarding how we actually equate the array defined in the function signature and the address that is passed from the function call. They two seem to be incompatible – RubyR Jan 08 '19 at 20:07
  • @user3655977 you can replace the signature by _void test(char * arr)_ and you will have exactly the same definition – bruno Jan 08 '19 at 20:09
  • Apologies if I am being a bit thick. Can you explain that when we pass an argument in a function call, how is it equated to the function parameter in its signature? Just like a direct assignment, right? But in this case, how would the `char arr[]` get equated to the `&arr[0]` address that we are passing? – RubyR Jan 08 '19 at 20:10
  • to have the type `char[]` or `char *` is equivalent for the parameter, is just 2 ways to write the same thing. And to call test with _arr_ or _&arr[0]_ is also exactly the same thing, just two ways to write the same thing – bruno Jan 08 '19 at 20:13
  • @bruno Even if I defined it as void test(char arr[10]), would it still ignore the 10 and consider it as just a char pointer? Wouldn't that mean loss of information (the value 10)? – RubyR Jan 08 '19 at 20:14
  • @user3655977 If you do that in C unfortunately you will not have even a warning, in C++ it is an error. – bruno Jan 08 '19 at 20:18
  • @user3655977 using the dimension 10 the compiler will consider the size is 10 in _test_, but if you use an index greater than 5 you go out of the vector into the stack This is why I never use C but C++, independently of the advantage of the class etc of course, it is more secure at compile time – bruno Jan 08 '19 at 20:20