5

Any historical or logical reasons behind it?


Explanation: when you pass an array to a function in C you actually only pass a pointer to an array. However, when you pass a struct, you can either pass a copy of the struct or the pointer.

//this:
int function(int array[10])
// is equivalent to this:
int function(int *array)
//and they both pass a pointer

//but this:
int function(struct tag name)
//passes a struct by value, where as this:
int function(struct tag *name)
//passes a pointer to it.

Why the difference?

Maverick Meerkat
  • 5,737
  • 3
  • 47
  • 66

5 Answers5

8

In the original K&R, you could not pass structs by value. That was a syntax error. Because many compiler vendors offered it as an extension, pass-by-value eventually made its way into the standard.

Why the restriction, and why the evolution? The machines that C was developed on were tiny. Segment sizes of 64 kilobytes were common. Memory was precious, so why copy something when you could just pass the address? Duplicating a 64-byte structure on the stack was an error, probably not even what the user intended.

By the mid-1990s, that wasn't true anymore. 32-bit addressing and RAM of 4 MB or more were common. The restriction was a hinderance and led to some complexity, because without const a structure passed by reference could be modified, perhaps unwittingly.

Why not do the same with arrays? No demand. Arrays and pointers are closely related in C, as you know. The C standard library depends heavily on passing by reference, consider memset and strcpy. Whereas passing a struct by value meant just dropping the & on the call, passing an array by value would have entailed adding new syntax. A compiler vendor that offered, say, by value as C syntax would have been laughed out of the conference.

James K. Lowden
  • 7,574
  • 1
  • 16
  • 31
0

int function(int array[10]) and int function(int *array) are the same because of 6.7.5.3 Function declarators (including prototypes) (http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf page 118)

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

.

Benoît
  • 3,355
  • 2
  • 29
  • 34
0

Of course, you can pass an array by value; all you need to do is wrap it in a struct. But that only works if the array has a definite (and non-variable) size. You can include an indefinitely sized array in a struct, but the resulting type is incomplete and can only be used as the target of a pointer.

That's probably as close as we're going to get to an explanation. The vast majority of arrays passed as arguments are not of fixed size, and passing them by value would not be possible, even if it were intended, which is also unlikely.

There is a similar (but different) decay with functions; a function cannot be passed as an argument, only function pointers. Since it would be tedious to explicitly write & every time you wanted to refer to a function, the language takes care of it for you.

On the whole, questions of the form "Why is this language like this snd not like that?" can only be answered "because that's how it is".

rici
  • 234,347
  • 28
  • 237
  • 341
-1

Types are different in both function declarations -

struct tag  /* and */ struct tag *

One is structure variable whereas another is pointer to structure.

You can do similar with structures -

int function(struct tag name[])  /*--> int function(struct tag *name)  */

These above would be equivalent.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • 3
    huh? how does this answer the question? – Maverick Meerkat Jul 23 '16 at 16:18
  • @DavidRefaeli I would assume . I think OP wasn't aware about this else he would not be confused about it . Question seems to me in that way because all decalrations in question desn't compare. – ameyCU Jul 23 '16 at 16:19
  • @ameyCU "I would assume" does not answer "how?". And DavidRefaeli is the OP. – melpomene Jul 23 '16 at 16:20
  • @melpomene Ohh didn't read the name with question . Okay but I would stand with my comment . And I think I have made clear that OP is comparing function with wrong type of arguements. – ameyCU Jul 23 '16 at 16:23
  • 2
    @ameyCU - I don't think you understand the question. I'm asking why is it that in C you can pass a copy of struct to a function, but you can't pass a copy of an array... – Maverick Meerkat Jul 23 '16 at 16:25
  • @DavidRefaeli In C ,array type passed to function is adjusted to pointer type . So basically it is treated as pointer as mentioned in standards . – ameyCU Jul 23 '16 at 16:27
  • 2
    @ameyCU Yes, and it seems the question is "why?". – hyde Jul 23 '16 at 17:12
-1

structs are used for declaring own kind of data types with primitive data types like int,float,long(or structs of structs) etc. they are supposed to hold a few of them e.g. struct of students will contain id,name,rollno,subjects,etc. so mostly any struct element will contain 10-20 fields at most (in logical cases), so when you pass a struct to a function, it has to copy 40-100 bytes approx. to make copy of that struct variables. where as arrays can be of huge size and are used to store same kind of information. they can be of size 10^7 in case of integers so if we implement a language to copy whole array for function calls it may have to copy (10^7)*4 bytes which is a huge amount and will impact the performance badly.and typical size of arrays is 10^4 to 10^6 which is still a lot. but if you create struct of array of int(or any other array) you can pass it to a function as a copy of that array. e.g.

#include<stdio.h>

typedef struct {
    int arr[10];
}arrayStruct;

void change(arrayStruct a){
    a.arr[2]=5;
}
int main(){
    arrayStruct a;
    for(int i=0;i<10;i++){
        a.arr[i]=i;
    }
    printf("Before:\n");
    for(int i=0;i<10;i++){
        printf("%d ",a.arr[i]);
    }
    change(a);
    printf("\nAfter:\n");
    for(int i=0;i<10;i++){
        printf("%d ",a.arr[i]);
    }
    return 0;
}

this is not done in most of the cases but few times when you need to pass arrays but don't want to alter the contents of them but also require some kind of changes to their copies and want to return that copy you can use this kind of structs of arrays and return them from functions of return type of structs e.g.

arrayStruct returnChange(arrayStruct a){
    a.arr[2]=332;
    return a;
}
kar09
  • 411
  • 3
  • 11