ed360463@cisunx.UUCP (02/27/87)
I have been aware of the post V7 C compilers passing and returning structs from procedures, and I am curious as to why. Passing structures as a whole seems to violate my impression of the nature of C. I feel that a good reason for passing arrays by reference (yes, I know that the pointer is passed by value :-) is to save an enormous ammount of stack and CPU time. To pass a structure by value seems to require an arbitrarily large amount of stack; but more importantly, non-atomic stack operations. That is, that I can push a long, int, char or any pointer with (hopefully) one machine-op. To pass a structure would require a number of pushes, a block-copy-op, or some looping copy code. I imagine that the people who added this to C had good reason, so could someone please tell me what I am missing or have gotten wrong? Thank you -- matt wartell university of pittsburgh {the known world}!pitt!cisunx!ed360463
ron@brl-sem.UUCP (02/27/87)
In article <3346@cisunx.UUCP>, ed360463@cisunx.UUCP (wartell m) writes: > > To pass a structure by value seems to require an arbitrarily > large amount of stack; but more importantly, non-atomic > stack operations. That is, that I can push a long, int, char > or any pointer with (hopefully) one machine-op. To pass > a structure would require a number of pushes, a block-copy-op, > or some looping copy code. Well your hopes are wrong. There are many machines that can not push anything on the stack in one operation. Even more enlighted machines with autodecrement indexed stack pointers or push instructions can't push the larger datatypes on the stack with one instruction. I'm not sure what point you are trying to make. There is a lot of stuff in the subroutine call sequence that is a lot more vulnerable to interruption than a single argument push. > I imagine that the people who added this to C had good reason, > so could someone please tell me what I am missing or have > gotten wrong? Mostly because it seemed that it would be silly not to. You can push and return any other data type (well almost any other, unions still don't work mostly). The only reason STRUCTS were initially left out was because they weren't easy to do. -Ron
guy@gorodish.UUCP (02/27/87)
>Passing structures as a whole seems to violate my impression >of the nature of C. I feel that a good reason for passing >arrays by reference (yes, I know that the pointer is passed by >value :-) is to save an enormous ammount of stack and CPU time. Yes, but the mere fact that something takes a lot of CPU time or stack space isn't sufficient to indicate that C shouldn't do it; some people, for instance, might argue that C implementations on the VAX shouldn't use "calls", because they take a lot of time :-). >To pass a structure by value seems to require an arbitrarily >large amount of stack; but more importantly, non-atomic >stack operations. That is, that I can push a long, int, char >or any pointer with (hopefully) one machine-op. Well, you can't. For instance, on the machine on which C was originally implemented, you *can't* push a long with one machine instruction. Again, "can I do this in a machine instruction" is the wrong question, as is "is this operation atomic". (Remember, the instruction to push such an item may not be atomic, even if it is done in one machine instruction; what if it takes a page fault when doing the push, or gets a segmentation violation because the stack hasn't grown far enough yet?) >I imagine that the people who added this to C had good reason, >so could someone please tell me what I am missing or have >gotten wrong? According to Dennis Ritchie (at least as far as I remember his answer to this question), the reason why structure assignment, structure-valued arguments, and structure-valued functions were added was to make C treat all scalar objects in a similar fashion.
herndon@umn-cs.UUCP (03/02/87)
Maybe my argument will be silly too, but the arguments that I have seen so far strike me as hilarious. As far as I can figure, no operation in original C ever did anything that incurred non-obvious costs in either space or time. By significant, I mean such as scanning an object of large size, allocating space for a pass-by-value array, etc. The user, if he needed to copy a structure or allocate a large array, was forced to do this himself, *explicitly*. Where C did allocate space for large objects, the declaration was apparent, e.g., "struct foo bletch[10000];". This is convenient for those who write performance sensitive code -- no innocent looking statement is going to chew up megabytes and megacycles of resources. In today's enlightened world, however, programmer convenience is more heavily stressed, and if the user wants it, the user gets it. My personal opinion is that this is the correct choice. I have, however, on many occasions, in a production environment, seen otherwise competent programmers wondering in disbelief at their programs when they get run-time errors from procedures that pass LARGE parameters by value on machines with memories only somewhat bigger than the parameters. It still amazes me how little some "professional programmers" understand "high-level language" compilers.
decot@hpisod2.UUCP (03/02/87)
> Mostly because it seemed that it would be silly not to. You can > push and return any other data type (well almost any other, unions > still don't work mostly). The only reason STRUCTS were initially > left out was because they weren't easy to do. Arrays were also left out. The only type of thing you still can't assign, pass, or return. Silly. And arrays are just as easy as structs to manipulate. It's just that it's difficult to find an inutitive syntax for array lvalues since the only reasonable one was foolishly grabbed to mean "no, you see, when it's an array name, it's really a pointer to the first element of the array, not the array itself, so that it looks sort of like you can pass arrays by value". Therefore, here's what I consider to be the next best syntax available for specifying array lvalues: identifier [] This refers to the entire array whose name is identifier. It is an invalid construction where the size of the array is not known. #define ARRSIZ 20 main () { int (reverse())[ARRSIZ]; /* function returning array [ARRSIZ] of int */ int arr[ARRSIZ] = "this is amazing"; arr[] = reverse(arr[]); printf("%s\n", arr); } int (reverse(s))[ARRSIZ] char s[ARRSIZ]; { char tmp[ARRSIZ], *tp = tmp; int i; for (i = strlen(s)-1; i >= 0; i--) *tp++ = s[i]; *tp = '\0'; return tmp[]; } Dave Decot hpda!decot
decot@hpisod2.HP.COM (Dave Decot) (03/04/87)
The example I provided to demonstrate a syntax for array lvalues incorrectly included several declarations for items which should have been "char" instead of "int". Here's the example again, corrected. Dave Decot hpda!decot #define ARRSIZ 20 main () { char (reverse())[ARRSIZ]; /* function returning array [ARRSIZ] of char */ char arr[ARRSIZ] = "this is amazing"; arr[] = reverse(arr[]); printf("%s\n", arr); } char (reverse(s))[ARRSIZ] char s[ARRSIZ]; { char tmp[ARRSIZ], *tp = tmp; int i; for (i = strlen(s)-1; i >= 0; i--) *tp++ = s[i]; *tp = '\0'; return tmp[]; }
cramer@kontron.UUCP (03/04/87)
> I have been aware of the post V7 C compilers passing and > returning structs from procedures, and I am curious as to > why. > > Passing structures as a whole seems to violate my impression > of the nature of C. I feel that a good reason for passing > arrays by reference (yes, I know that the pointer is passed by > value :-) is to save an enormous ammount of stack and CPU time. > > To pass a structure by value seems to require an arbitrarily > large amount of stack; but more importantly, non-atomic > stack operations. That is, that I can push a long, int, char > or any pointer with (hopefully) one machine-op. To pass > a structure would require a number of pushes, a block-copy-op, > or some looping copy code. > > I imagine that the people who added this to C had good reason, > so could someone please tell me what I am missing or have > gotten wrong? > > matt wartell One reason I have for occasionally passing a structure, rather than a pointer to the structure, is if the structure is purely an input, and I want to make sure that the called function doesn't alter the caller's copy of the structure. Clayton E. Cramer
markb@sdcrdcf.UUCP (03/04/87)
I always thought that it was added so that people who do complex math
would not have do any pointer hacking. It is a lot nicer to be able to
write:
a = c_add(c_mul(b,c),d);
then
{ struct cmplx t;
c_mul(&t,&b,&c);
c_add(&a,&t,&d);
}
Mark Biggar
{allegra,burdvax,cbosgd,hplabs,ihnp4,akgua,sdcsvax}!sdcrdcf!markb
aglew@ccvaxa.UUCP (03/12/87)
...> Why pass structs by value? I occasionally feel uncomfortable passing structs by value, and receiving them as the return value of the function. Frequently because the struct starts offsmall, 16 - 32 bits (eg. struct RectCoord { short x, y; }), so I say "I should use pass by value here because they structure is no bigger than an int". But then I start adding stuff to the struct, more fields, reference counts... The only things that I don't feel guilty about are typedef struct Complex { float re, im; } Complex; and typedef LongLong { unsigned hi, low; } LongLong; the latter because the machine I work on has 64 bit integer instructions, though the C compiler doesn't give you access to them.
rjv@ihdev.UUCP (03/12/87)
In article <28700009@ccvaxa> aglew@ccvaxa.UUCP writes: > >...> Why pass structs by value? because my struct is a chess-board, and i happen to be doing some recursive backtracking algorithms (for example) ron vaughn ...!ihnp4!ihdev!rjv