3

In C:

  • When a struct is sent (via a parameter) by value in to a function, a new struct is created, so changing the structure inside the function won't change the original structure.

  • When an array is sent (via a parameter) by value in to a function, a new pointer is created, so changing the array inside the function won't change the original array, but changing array values inside the function (since we have the pointer to the original array) will change the values in the original array.

  • When a struct with an array field is sent (via a parameter) by value in to a function, ????? is created, so that changing the array (pointer) inside the function won't change the original array and changing array values won't change the values in the original array.

Does the third point mean that an array field of a struct, when sent in to a function will be entirely cloned? Why isn't just the pointer used instead? What does the specification say about it?

A piece of code that I've played with:

typedef struct {
    int value;
    int array[3]; /* initialized to 0 by default */
} Struct_t;

void foo(Struct_t structure)
{
    printf("-- %p\n", structure.array); /* Pointer to local array */

    structure.value = 1;
    *structure.array = 1;       /* Won't change the original array */
    *(structure.array + 1) = 1; /* Won't change the original array */
    structure.array[2] = 1;     /* Won't change the original array */
}

int main()
{
    Struct_t s = { .value = 0 };

    foo(s);

    printf("-- %p\n", s.array); /* Pointer to original array */

    printf("%d\n", s.value);
    printf("%d\n", s.array[0]);
    printf("%d\n", s.array[1]);
    printf("%d\n", s.array[2]);
}

Output:

-- 0x7ffe8f17d194
-- 0x7ffe8f17d1b4
0
0
0
0
alk
  • 69,737
  • 10
  • 105
  • 255
Dorin Botan
  • 1,224
  • 8
  • 19
  • 3
    The array is part of the struct and so it also will be copied (all the values in it). If it would be a pointer, only the pointer will be copied and therefore will point to the same memory as the original. – mch Sep 13 '18 at 12:05
  • "*changing the array inside the function won't change the original array, but changing array values inside the function*" an "*array*" **is** its "*values*"/"elements", nothing more nothing less. – alk Sep 13 '18 at 13:39

4 Answers4

5

OP's "When an array is sent ..." needs clarification.

When an array is sent (via a parameter) by value in to a function, a new pointer is created, so changing the array inside the function won't change the original array, but changing array values inside the function (since we have the pointer to the original array) will change the values in the original array. (OP)

When an array, like s[] below, is passed to strcpy(char *s1, const char *s2), a conversion occurs first. The object s is converted to the address of the first element of the array. strcpy() does not receive s[] as the s1 parameter, instead it receives a copy of the value of of &s[0].

char s[6] = "Hello";
strcpy(s, "World");

Within strcpy(), s1 is not an array. s1 is a pointer to a char. strcpy() has no concept of "changing the array inside the function" as the function does not know s1 points to array memory, allocated memory or anything else. strcpy() understands s1 points to a char.


Does the third point mean that an array field of a struct, when sent in to a function will be entirely cloned?

Yes. When an object is passed to a function in C, it is potentially converted and then passed by value. It is much like any assignment. The contents of the object, after conversion is copied to the destination. It makes no difference, after conversion, if the object is a struct, union, int, double, void*, int(*)() etc or a struct containing an array.

int a;
double b;
a = 5;  // 5 is copied to a
b = a;  // a is converted to double and copied to b


char s[6] = "Hello";
char *e;
void *v;
e = s; // s is converted to the address on the first array element and then copied to e
v = e; // e is converted to a `void*` and then copied to v

Struct_t f = {0};
Struct_t g;
g = f; // f is copied to g
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

Does the third point mean that an array field of a struct, when sent in to a function will be entirely cloned?

Yes.

Why isn't just the pointer used instead?

Because there is no pointer. An array is not a pointer. (More on this here.)

alk
  • 69,737
  • 10
  • 105
  • 255
0

In C everything is pass-by-value.

  1. When we pass-by-value we are passing a copy of the variable to a function.

  2. When we pass-by-reference we are passing an alias of the variable to a function.

    It is copying the value of the pointer, the address, into the function.

If a struct is passed by value to a function the bytes of the struct are copied as the function parameter. Anything done to that struct within the function changes the copy, not the original struct

kiran Biradar
  • 12,700
  • 3
  • 19
  • 44
  • Does this mean that an array in the struct will be entirely a part of that structure, and not just a pointer to the values located somewhere else in the memory? Seems so, since sizeof(struct) is the sum of the sizes of all elements in the array in the struct. But is there a specific reason for doing so? Won't this potentially cause performance issues? – Dorin Botan Sep 13 '18 at 12:24
  • I know that passing `struct`s by value was not allowed in K&R and was added later. What do the new specifications say about this? What an array in a `struct` actually is and why is it so? – Dorin Botan Sep 13 '18 at 12:29
  • @DorinBotan The array is part of the struct. Use `sizeof(Struct_t)` to verify (note: may be larger than expected - see [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](//stackoverflow.com/q/119123)) – 001 Sep 13 '18 at 12:32
0

A struct is a predefind structure of memory, that has a certain memory layout. By adding an array to the struct the actual memory of the array is located in the struct not a pointer. That is why it has to be copied with the rest of the struct.

Arrays are not pointers, an arrays has a specific unchangable memory location, while a pointer can point anywhere you want.

Kami Kaze
  • 2,069
  • 15
  • 27