1

Look at the code given below, here price,quantity and amount are local to main function we pass them to extend where PRICE,QUANTITY and amount are format argument local to the function. My question is how change in amount which is local to void extend will reflect in main without using pointers.

#include <stdio.h>

void extend(float[], float[], double[]);

int main(void) {

    float price[10] = { 10.62, 14.89, 13.21, 16.55, 18.62, 9.47, 6.58, 18.32, 12.15, 3.98 };
    float quantity[10] = { 4, 8.5, 6, 8.35, 9, 15.3, 3, 5.4, 2.9, 4.8 };
    double amount[10] = { 0 };
    extend(price, quantity, amount);
    for (int i = 0; i < 10; i++) {
        printf("%f ", amount[i]);
    }
   return 0;
}

void extend(float PRICE[], float QUANTITY[], double amount[]) {
    for (int i = 0; i < 10; i++) {
        amount[i] = PRICE[i] * QUANTITY[i];
    }
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 3
    arrays are pointers – Garr Godfrey Sep 20 '21 at 17:24
  • 5
    @GarrGodfrey [No](https://stackoverflow.com/questions/1641957/is-an-array-name-a-pointer). – DYZ Sep 20 '21 at 17:26
  • 3
    Arrays decay into pointers, they aren't pointers. – Hatted Rooster Sep 20 '21 at 17:27
  • @GarrGodfrey Arrays are not pointers. The name may decay to a pointer, but that doesn't mean they are the same. Just try `sizeof(int[10])` and `sizeof(int*)` and see the difference: https://wandbox.org/permlink/N59BiOAYlfyf06UV – NathanOliver Sep 20 '21 at 17:28
  • @DYZ the compiler sees the array differently than a pointer in many cases. At runtime, not so much. Even the compiler doesn't know the difference if the size isn't provided in an array parameter. It's a distinction without a difference – Garr Godfrey Sep 20 '21 at 17:30
  • @GarrGodfrey You may be confused because `void func(int a[])` is the same thing as `void func(int *a)`. In both cases the parameter is a pointer. But `int a[10]` is an array, *not* a pointer. You can pass it to `func` because `a` will decay into a pointer to the first element when you call the function. – Kevin Sep 20 '21 at 17:32
  • 1
    @GarrGodfrey for a 1D array argument, the compiler will *completely ignore* any array size given. It is only needed for a multi-dimensional array to figure out the indexing. – Weather Vane Sep 20 '21 at 17:32
  • @GarrGodfrey: you may like section 6 of the [comp.lang.c FAQ](http://c-faq.com). – pmg Sep 20 '21 at 17:34
  • The question is about function parameters, hence an array is a pointer (in that context) – Garr Godfrey Sep 20 '21 at 17:35
  • @GarrGodfrey It would be more correct to say that you cannot pass an array by value and that they decay to pointers than saying that arrays are pointers, especially without first mentioning that you're only talking about parameters. There are arrays in the `main` function so we couldn't tell that you aren't talking about those when you made your original comment. – Kevin Sep 20 '21 at 17:39
  • Same code was part of a [question](https://stackoverflow.com/questions/69253993/how-can-i-pass-an-array-as-a-parameter) asked a few hours before. – H.S. Sep 20 '21 at 17:50
  • 1
    @GarrGodfrey: Trying to hold up “arrays are pointers” is pointless. First, they are not, as defined by the C standard. Further, when a person implements a compiler, the difference becomes quite apparent; the notion that “Well, an array kind of works like a pointer” vanishes when you have to actually make the details work. Second, students should not be taught this. They need to know the differences, so statements that conflate them are detrimental. They should think in terms of converting arrays to pointers and adjusting parameters, not in terms of arrays are pointers. – Eric Postpischil Sep 20 '21 at 17:52

1 Answers1

2

You are mistaken. Actually the function uses pointers. This function declaration

void extend(float[], float[], double[]);

is adjusted by the compiler to the following declaration

void extend(float *, float *, double *);

From the C Standard (6.7.6.3 Function declarators (including prototypes))

7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

And when the function is called like

 extend(price, quantity, amount);

the array designators price, quantity and amount are implicitly converted to pointers to their first elements. So in fact elements of the arrays are passed by reference indirectly through pointers to first elements. Using the pointer arithmetic the elements of the array amount can be changed within the function

amount[i] = PRICE[i] * QUANTITY[i];

From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Pay attention to that for example this expression amount[i] is equivalent to *( amount + i ).

From the C Standard (6.5.2.1 Array subscripting)

2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335