throopw@rtp47.UUCP (Wayne Throop) (09/04/85)
All right. Put on your C array thinking caps. Consider the following program: void f(x) int x[2][2][2]; { printf( "%o %o %o\n", x, x[0], x[0][0] ); printf( "%d %d %d\n", sizeof(x), sizeof(x[0]), sizeof(x[0][0]) ); } void main(){ int x[2][2][2]; printf( "%o %o %o\n", x, x[0], x[0][0] ); printf( "%d %d %d\n", sizeof(x), sizeof(x[0]), sizeof(x[0][0]) ); f(x); } Clearly the printfs are "illegal", but assume you have a fairly vanilla machine. Eight-bit bytes, four-byte ints. Four-byte pointers. Pointers and ints stored in the same way for argument passing. Two questions: - What does this program print? (Especially what is printed on the last output line?) - Is this "correct"? (Again, especially the last line.) I think that most systems will print "4 16 8" (or equivalent) as the last line. While this is (probably) not a bug, I think it is at least a misfeature. This same point was part of the "C bites" topic, which is what drew my attention to it. The point is *should* C bite in this way, and if so, why? -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!rtp47!throopw
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (09/07/85)
> void f(x) > int x[2][2][2]; > { > ... > } > void main(){ > int x[2][2][2]; > ... > f(x); > } > ... > I think that most systems will print "4 16 8" (or equivalent) ... Yes, you are not actually passing an entire array to the function f() but rather just a pointer to a 2x2 array of ints. C lets you misdeclare this void f( int x[2][2][2] ); /* ANSI C assumed */ which is the real misfeature. The "correct" declaration is technically void f( int (*x)[2][2] ); which also is supported by C (thankfully), or if you prefer, void f( int x[][2][2] ); Fortunately, old C did not have this misfeature for structs/unions, so it was possible to add to C the ability to pass struct arguments in addition to just pointers to them. For reasons of backward compatibility, it is unfortunately NOT possible to change C so that f( x ); actually passes the array and not just a pointer to the first element. Maybe language "D" can fix all C's mistakes (ha). Meanwhile we just have to learn to cope with them.
anton@ucbvax.ARPA (Jeff Anton) (09/07/85)
In article <171@rtp47.UUCP> throopw@rtp47.UUCP (Wayne Throop) writes: >Consider the following program: > > void f(x) > int x[2][2][2]; > { > printf( "%o %o %o\n", x, x[0], x[0][0] ); > printf( "%d %d %d\n", sizeof(x), sizeof(x[0]), sizeof(x[0][0]) ); > } > void main(){ > int x[2][2][2]; > printf( "%o %o %o\n", x, x[0], x[0][0] ); > printf( "%d %d %d\n", sizeof(x), sizeof(x[0]), sizeof(x[0][0]) ); > f(x); > } >Clearly the printfs are "illegal", but assume you have a fairly vanilla >machine. Eight-bit bytes, four-byte ints. Four-byte pointers. >Two questions: > - What does this program print? > (Especially what is printed on the last output line?) > - Is this "correct"? (Again, especially the last line.) > >I think that most systems will print "4 16 8" (or equivalent) as the >last line. While this is (probably) not a bug, I think it is at least a >misfeature. This same point was part of the "C bites" topic, which is >what drew my attention to it. The point is *should* C bite in this way, >and if so, why? >-- >Wayne Throop at Data General, RTP, NC ><the-known-world>!mcnc!rti-sel!rtp47!throopw sizeof returns the size of the object. Since arrays are passed as addresses which are put into pointer vars, sizeof(x) in the called function should be the sizeof the pointer. Are you proposing that C should pass the dimentions of the array also so a called function can know these things? Or maybe since the pointer was declared as 'int x[2][2][2];' you want sizeof x to be 8 ints? I prefer to keep C's ability to pass pointers to arrays or subarrays. A use of sizeof often has the address taken also so returning the size of the pointer not the array it points to prevents a careless programmer from stomping over memory. As far as debugging goes, I hate large memory updates that might run to far or not far enough. They are probably the must tricky bugs around. If you know the size of an array because you know its dimensions, you might as well put a #define XSIZE 2*2*2*sizeof(int) in near your declaration. Perhaps it might be nice to pass array dimensions by arguments to function calls. -- C knows no bounds. Jeff Anton U.C.Berkeley Ingres Group ucbvax!anton anton@BERKELEY.EDU
root@bu-cs.UUCP (Barry Shein) (09/09/85)
>From: gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) >Subject: Re: C array follies 1 > >Maybe language "D" can fix all C's mistakes (ha). Meanwhile we just >have to learn to cope with them. "The C Programming Language", Ritchie et al, BSTJ V57, No. 6, Part 2, 1978, page 2019: "...C would probably have to be left as is, and a totally now language developed. We leave it to the reader to speculate whether it should be called D or P." (very last sentence in the article.) For your amusement. -Barry Shein, Boston University Spoiler: To prevent 10**27 'why P?'s: first BCPL, then B, then C...(P ... L...)
throopw@rtp47.UUCP (Wayne Throop) (09/10/85)
> > [Original article questions practice of having sizeof an array > > formal always return pointer size] > ... Are you proposing that C should pass the dimentions of the array > also so a called function can know these things? Or maybe since the > pointer was declared as 'int x[2][2][2];' you want sizeof x to be 8 > ints? I am suggesting that the latter notion is a good idea. In particular, the formal declaration int x[3]; should make sizeof(x) == (sizeof(int) * 3). The formal declaration int *x; should make sizeof(x) == sizeof(int *). The formal declaration int x[]; is a problem. I would prefer it if sizeof(x) yeilded a diagnostic. Failing that, sizeof(x) == sizeof(int *) is next best, I suppose. > I prefer to keep C's ability to pass pointers to arrays or subarrays. So do I. The above suggestion does not affect this. It only affects what happens when sizeof is applied to such a formal name. I dislike the incongruity that in this code fragment void f(x) int x[3]; { int y[3]; ... } sizeof(x) != sizeof(y). This seems like a misfeature to me. -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!rtp47!throopw
guy@sun.uucp (Guy Harris) (09/12/85)
> I am suggesting that the latter notion is a good idea. In particular, > the formal declaration > int x[3]; > should make sizeof(x) == (sizeof(int) * 3). An alternative is simply to forbid such a formal declaration. foo(x) int *x; { x++; } would, if "x" pointed to the "i"th element of an array of "int"s, cause "x" to point to the "i+1"st element of that array. foo(x) int x[3]; { x++; } would cause great confusion, since foo() { int x[3]; x++; } is illegal. C doesn't permit you to pass arrays by value, so I think foo(x) int x[3]; { ... is meaningless. If C permitted you to take the address of an array other than a subarray, foo(x) int (*x)[3]; { ... might be meaningful and useful (it says that "foo" takes a pointer to an array with 3 "int" elements - not 4, not 2, but 3 and only 3). However, you can't take the address of such an array, so bar() { int y[3]; foo(&y); } is illegal. C's "declaration syntax == usage syntax" breaks down when it comes to arrays. int a[3]; a[1] = 1; *(a + 2) = 2; is legal, and would also be legal if "a" were declared as int *a; However, the code, while still legal C, would mean something very different in the second form. Since a declaration of a formal argument is, not surprisingly, a declaration, and since the declarations "int a[];" and "int *a;" are inequivalent if "a" is not a formal argument, I don't think array declarations and pointer declarations should be equivalent for formal arguments. Since it is nonsensical to declare an array formal, it should be made illegal or, at least, deprecated - too much code uses "int a[];" as a synonym for "int *a;" when declaring a formal to simply forbid it. Guy Harris
throopw@rtp47.UUCP (Wayne Throop) (09/14/85)
> > the formal declaration > > int x[3]; > > should make sizeof(x) == (sizeof(int) * 3). > > An alternative is simply to forbid such a formal declaration. > ... > foo() { int x[3]; x++; } > is illegal. [and thus by analogy the formal should be made illegal] > Guy Harris I agree that this is better than the current situation. Interestingly enough, while lint raises not a peep in the following example for b, our local typechecker has something different to say about this: 1 void f(a,b) 2 int *a, b[]; 3 { 4 int *c, d[1]; 5 ++a; 6 ++b; 7 ++c; 8 ++d; 9 } #1017 6 not an lvalue (:IDENTIFIER b :AUTO ... ) #1017 8 not an lvalue (:IDENTIFIER d :AUTO ... ) therefore, my code already obeys this restriction. I also try to remember to declare formal arrays as pointers always. However, I still think that if formal arrays are to be allowed, they "ought to" have the sizeof properties I outlined before. -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!rtp47!throopw