jst@abic.UUCP (Shack Toms) (03/05/86)
I have noticed that different compilers treat the & operator differently when it is applied to arrays. In particular, the UNIX compiler I have been using warns against it. K&R explicitly deny its legality. However, the operation seems to me to be perfectly reasonable when the desired result is a pointer to the array rather than a pointer to the first element of the array. For example, typedef int foo[5]; foo x, y[3], *z; if sizeof(int) == 4 then -- sizeof *z == 20 sizeof &**z == 4 if pointers are 4 bytes sizeof x == 20 sizeof y[2] == 20 sizeof **z == 4 sizeof *x == 4 sizeof *y[2] == 4 z = &x is illegal although the types would match z = x is quasi-legal, the types mismatch, lint should complain z = &y[2] is illegal, for no good reason (my opinion) z = y + 2 is legal (int *) z == *z /* The pointer to array == pointer to first element */ (int *) (z + 1) != *z + 1 /* But their types differ (with implications) */ (int *) (y + 2) == y[2] y[2]+1 is a pointer to y[2][1] &y[2]+1 should be a pointer to y[3], but is illegal The algorithms in question use z as a pointer to an array (usually) within arrays. It is useful sometimes to have z point to an isolated array however. The pointer increment operation (z++) is useful, so it is desireable to not interchange the meanings of (pointer to array) and (pointer to first element of array). Where allowed in the language, an array name as an lvalue refers to the entire array (e.g. sizeof) wheras an array name as an rvalue evaluates to a constant pointer to the first element of the array. Trying to use this to solve the problem, I create 'foo' as a struct which contains the array as its sole field. Then, when I want to access the array as an lvalue, I use the struct name. When I want to access the array as an rvalue, I use the field name. This ends up looking like: typedef struct { int r[5]; } foo; foo x, y[3], *z; if sizeof(int) == 4 then -- sizeof *z == 20 sizeof &*(*z.r) == 4 if pointers are 4 bytes sizeof x == 20 sizeof y[2] = 20 sizeof *(*z.r) == 4 sizeof *(x.r) == 4 sizeof *(y[2].r) == 4 z = &x now legal and produces the desired result z = x.r is just as quasi-legal as before z = &y[2] now legal and produces the desired result z = y + 2 is still legal (int *) z == *z.r /* The pointer to array == pointer to first element */ (int *) (z + 1) != *z.r + 1/* But their types differ (with implications) */ (int *) (y + 2) == y[2].r y[2].r+1 is a pointer to y[2].r[1] &y[2]+1 is a pointer to y[3], now is legal This now does everything I would like with (y[2] = x) now being legal as a bonus (on compilers which allow structure assignments.) The problem is that it is clumsy to have to keep writing .r whenever the array is used as an rvalue. Since the generalization of array references so that lvalues are defined (and refer to the entire array) is useful, and is compatible with the rest of the language definition, and is allowed in many existing compilers... Why not make it official? I am aware that this does not help with array assignments (as 'struct foo' does.) Any comments? Shack Toms @ Allen-Bradley -- Is it warm in here, or is it just me?
greg@utcsri.UUCP (Gregory Smith) (03/08/86)
In article <750@abic.UUCP> jst@abic.UUCP (Shack Toms) writes: >I have noticed that different compilers treat the & operator differently >when it is applied to arrays. In particular, the UNIX compiler I have >been using warns against it. K&R explicitly deny its legality. >However, the operation seems to me to be perfectly >reasonable when the desired result is a pointer to the array rather >than a pointer to the first element of the array. For example, >[examples] The problem is that & can only be used on lvalues, and an array can never be an lvalue, even though its address is known. This is done because of the automatic 'array-to-pointer' conversion in C. If an array was an lvalue, what could you assign to it? another array! but this second array reference would be automatically converted to a pointer so that wouldn't work. I agree that it is really a design flaw in the language, to make it illegal to form a pointer to an array. & should work on any 'object' ( an object of known type residing in memory at a computable address ) where an object is an lvalue or an array. The problem could also be solved by allowing arrays to be lvalues. The array-to-pointer conversion would have to be suppressed depending on the operation being done on the array. If the array was the object of a &, or if it was on one side of an '=', with an identical type array on the other side, the array-to-pointer conversion would not be done. This would allow array assignments within the current syntax of c. It would not allow arrays to be passed as parameters, though, since parameter types of called functions are not known to the compiler. The semantics as described above for the '=' operator would probably very messy to implement, too. For these reasons I think that & should be allowed but not =. Incidentally, the language as described in K&R requires the array-to-pointer type conversion to be supressed depending on the context of the array, but only in one case, the object of a sizeof: char line[80]; sizeof( line ) == 80 /* line not converted to (char*) */ sizeof( line+1 ) == 4 /* or 2 or whatever sizeof(char*) is */ This exception is noted in K&R 7.2 : "When [ sizeof is ] applied to an array, the size is the total number of bytes in the array". I.e. they are noting that it is a special case of array treatment. (7.2 of the language reference, Appendix A ). Adding another, similar special treatment would allow pointers to arrays. '&line' in the above example would be of type ( char (*)[80]). -- "So this is it. We're going to die." - Arthur Dent ---------------------------------------------------------------------- Greg Smith University of Toronto ..!decvax!utzoo!utcsri!greg
throopw@dg_rtp.UUCP (Wayne Throop) (03/09/86)
> I have noticed that different compilers treat the & operator differently > when it is applied to arrays. In particular, the UNIX compiler I have > been using warns against it. K&R explicitly deny its legality. > However, the operation seems to me to be perfectly > reasonable when the desired result is a pointer to the array rather > than a pointer to the first element of the array. I agree that C's treatment of array/function/struct addresses is inconsistant, confusing, and limiting. In essence a small notational convenience was traded for a large consistancy headache. I think the tradeoff was wrong, but I'm not sure that your proposal would clarify things. I'd hesitate to evaluate textually and syntactically identical constructs differently based on whether an lvalue or an rvalue is needed in the current context. This would pile more confusion on an already dismal situation. -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
kwh@bentley.UUCP (KW Heuer) (03/11/86)
In article <211@dg_rtp.UUCP> dg_rtp!throopw (Wayne Throop) writes: >I agree that C's treatment of array/function/struct addresses is >inconsistant, confusing, and limiting. In essence a small notational >convenience was traded for a large consistancy headache. I think the >tradeoff was wrong ... Yeah, arrays are really second-class citizens in C. I think it would have been possible to make the array a "real" datatype, with [] an array (rather than pointer) operator; I'd be quite willing to write &a[0] in lieu of the automatic array-to-pointer conversion. Of course it's too late to change things in C; too many programs depend on it. And C++ is committed to C compatibility. Are there any plans for a "D" language? I already posted my comments on function addresses, so I won't discuss them here. Why do you include struct addresses in your complaint? I don't see anything inconsistent, confusing, or limited in them, at least nothing analagous to function and array addresses. Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint.
rbj@icst-cmr (Root Boy Jim) (03/12/86)
From: Wayne Throop <dg_rtp!throopw> Subject: Re: Address of array Date: 9 Mar 86 05:02:13 GMT To: info-c@brl-smoke.arpa > I have noticed that different compilers treat the & operator differently > when it is applied to arrays. In particular, the UNIX compiler I have > been using warns against it. K&R explicitly deny its legality. > However, the operation seems to me to be perfectly > reasonable when the desired result is a pointer to the array rather > than a pointer to the first element of the array. I agree that C's treatment of array/function/struct addresses is inconsistant, confusing, and limiting. I diagree violently (so what else is new?). The resolution of pointers and arrays is one of the *strengths* of C. Admittedly there are a few glitches, such as when the sizeof operator is applied to an array. Ironically, this glitch was added to *help* the user. Personally, when a formal parameter is declared as a local array, I would like to see sizeof return the same as if it was a global. In essence a small notational convenience was traded for a large consistancy headache. I think the tradeoff was wrong, but I'm not sure that your proposal would clarify things. I'd hesitate to evaluate textually and syntactically identical constructs differently based on whether an lvalue or an rvalue is needed in the current context. This would pile more confusion on an already dismal situation. All the compilers I've seen give a warning, but generate &array[0].
davidsen@steinmetz.UUCP (Davidsen) (03/14/86)
In article <211@dg_rtp.UUCP> throopw@dg_rtp.UUCP (Wayne Throop) writes: >> I have noticed that different compilers treat the & operator differently >> when it is applied to arrays. In particular, the UNIX compiler I have >> been using warns against it. K&R explicitly deny its legality. >> However, the operation seems to me to be perfectly >> reasonable when the desired result is a pointer to the array rather >> than a pointer to the first element of the array. > >I agree that C's treatment of array/function/struct addresses is >inconsistant, confusing, and limiting. In essence a small notational >convenience was traded for a large consistancy headache. I think the >tradeoff was wrong, but I'm not sure that your proposal would clarify >things. I believe that to support reasonable portable code C *must* allow the address operator on an array, even if it is not required. Consider: prog.c: #include "globals.h" /* project global symbols and types */ foo() { LOCAL m,n; process(&m); } globals.h: typedef long LOCAL[10]; ================ Since LOCAL is a typedef which is an array, the programmer would not be able to write code which would work with a legal typedef for LOCAL unless the & operator was allowed for an array. To require special code to handle arrays and scalars defeats the intent of information hiding, and requires global changes to the source is a typedef is changes, for instance, from an array to a structure. This was pointed out to me by someone on X3J11, but I can't remember who in order to give credit for this example. -- -bill davidsen seismo!rochester!steinmetz!--\ / \ ihnp4! unirot ------------->---> crdos1!davidsen \ / chinet! ---------------------/ (davidsen@ge-crd.ARPA) "It seemed like a good idea at the time..."
throopw@dg_rtp.UUCP (Wayne Throop) (03/17/86)
>>I agree that C's treatment of array/function/struct addresses is >>inconsistant, confusing, and limiting. [...] > [...] Why do you include struct addresses in your complaint? I don't see > anything inconsistent, confusing, or limited in them, at least nothing > analagous to function and array addresses. Ah. Perhaps that *was* confusing of me. I didn't mean to imply that handling of arrays, functions and structures are all incorrect. Just that the treatment of each of these is not like the treatment of either of the others. In some sense, there isn't a "right" way to do it... it's just that C doesn't treat similar cases (aggregates like arrays and structs, for example) in analogous ways, and this is inconsistant. > Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint. -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
jsdy@hadron.UUCP (Joseph S. D. Yao) (03/18/86)
In article <2293@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: >In article <750@abic.UUCP> jst@abic.UUCP (Shack Toms) writes: >>I have noticed that different compilers treat the & operator differently >>when it is applied to arrays. In particular, the UNIX compiler I have >>been using warns against it. K&R explicitly deny its legality. >>However, the operation seems to me to be perfectly >>reasonable when the desired result is a pointer to the array rather >>than a pointer to the first element of the array. ... >I agree that it is really a design flaw in the language, to make >it illegal to form a pointer to an array. & should work on any >'object' ( an object of known type residing in memory at a computable >address ) where an object is an lvalue or an array. >... I don't think it's reasonable to call this a flaw. In fact, most C compilers of which I am aware will tacitly (or sometimes with noisy complaint) accept &array_name to be identical to array_name. The problem is, an array name is often used as a _constant_ of type pointer-to-______. You cannot take the address of other constants (e.g. &1). It might be nice to generate an object containing the constant, and take the address of that; but that's for more complex and unmanageable languages than C. [Gentle reader: before flaming me down to slime, please stop and think how this -- admittedly slightly off-beat -- model of an array name fits the usage, and how it might be a nice alternative view to your own.] The history, of course, is that in early C only atomic objects could be manipulated in single operations, like assignament or function arguments or returns. An array is not an atomic object. A pointer is. Therefore, when you needed to use an array name as an atomic object, you had to coerce it to a constant of type ptr-to-___. A few obvious inconsistencies show up that are a result of this: int x[5]; sizeof(x) == 5*sizeof(int), because we are referring to the array as a whole; sizeof(x + 1) == sizeof(int *), because to add we have to coerce it to pointer, etc. and, of course, when passed as an argument only the address strains through. I don't really see what the problem is that people are moaning about. If you want a pointer to the array, the array name itself coerces to a pointer containing the memory location at the beginning of the array. There is no such thing as a pointer to the whole array: that is a Pasqualische or Fortranian notion. Pointers, in C, only point to atomic or aggregate (structure/union) objects. I whole-heartedly agree that for some uses it is rather nice to use such things. That is why (excuse me while I put on my flak jacket and asbestos suit) C is not the only language in the world worth using. (Just, almost.) -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
throopw@dg_rtp.UUCP (Wayne Throop) (03/18/86)
> [...] C's treatment of array/function/struct addresses is > inconsistant, confusing, and limiting. > > I diagree violently (so what else is new?). The resolution of pointers > and arrays is one of the *strengths* of C. Actually, you disagree needlessly :-). I said that things were treated inconsistantly, not that array/pointer equivalence is a not-good idea. > Admittedly there are a few glitches, Ah, you've noticed that too, eh? > such as when the sizeof operator is applied to an array. Ironically, > this glitch was added to *help* the user. Glitches added to help the user are still glitches. And, in the end, I question whether they actually help the user. > Personally, when a formal > parameter is declared as a local array, I would like to see sizeof > return the same as if it was a global. You too? Good. You listening, ANSI? > In essence a small notational > convenience was traded for a large consistancy headache. I think the > tradeoff was wrong, [...] > > All the compilers I've seen give a warning, but generate &array[0]. Let me clarify what small notational convenience and what consistancy headache I am talking about here. The notational convenience is that an array name "means" the address of the first element of the array. The consistency headache is that then addressing (and "mentioning") of arrays and other things (such as structs) does not behave similarly, and it becomes impossible to (legally, formally) take the address of an entire array (at least, without adding warts to the warts and making yet another "glitch"). The idea of array/pointer equivalence would cause *much* fewer problems if the question of notational convenience of passing arrays (by reference) hadn't clouded the issue. This led directly to the common confusions about whether definitions of pointers reserve space for the items pointed to (and as to whether array declarations do, also), the confusion of whether a structure name indicates the address of the structure or it's contents, the inability to treat arrays by value (since you get a reference whenever the name of the array is mentioned), and so on and on. I am not arguing here from a "language purity" high horse. I am saying that actual experience with C and the type of errors that are commited in the use of C make me think that the treatment of array and function addressing (and the fact that these things are different from struct addressing) has spread confusion. Further, this confusion has made the C language much harder to master then it "ought" to be, and has obscured some of its strong points, such as array/pointer equivalence. -- Wayne Throop at Data General, RTP, NC <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
rh@cs.paisley.ac.uk (Robert Hamilton) (03/19/86)
>In article <211@dg_rtp.UUCP> throopw@dg_rtp.UUCP (Wayne Throop) writes: >>> I have noticed that different compilers treat the & operator differently >>> when it is applied to arrays. In particular, the UNIX compiler I have >>> been using warns against it. K&R explicitly deny its legality. >>> However, the operation seems to me to be perfectly >>> reasonable when the desired result is a pointer to the array rather >>> than a pointer to the first element of the array. >> >>I agree that C's treatment of array/function/struct addresses is >>inconsistant, confusing, and limiting. In essence a small notational >>convenience was traded for a large consistancy headache. I think the >>tradeoff was wrong, but I'm not sure that your proposal would clarify >>things. > >I believe that to support reasonable portable code C *must* allow the address >operator on an array, even if it is not required. Consider: > >prog.c: > #include "globals.h" /* project global symbols and types */ > > foo() { > LOCAL m,n; > > process(&m); > } > >globals.h: > typedef long LOCAL[10]; > >================ >Since LOCAL is a typedef which is an array, the programmer would not be >able to write code which would work with a legal typedef for LOCAL >unless the & operator was allowed for an array. To require special code >to handle arrays and scalars defeats the intent of information hiding, >and requires global changes to the source is a typedef is changes, for >instance, from an array to a structure. Taking the address of an array just doesnt make sense in C. You can see the reason if you know why the following bit of code also won't work: int a[10]; int *b; a=b; /* makes no sense */ a+=1; /* ditto */ b=a; /* ok of course */ The decl. a[10] does 2 things: 1. reserves storage for 10 elements 2. lets the compiler know that "a" is an int * to of the first element reserved. It does *not* reserve storage for a pointer to the storage. So "&a" only exists during compilation, in the sense that the compiler holds the address of the reserved storage somewhere that "somewhere" has an address at compile time. The decl. int *b on the other hand does 2 different things. 1. lets the compiler know that "b" is an int * ( for pointer arithmetic) 2. and reserves a storage location for b. so &b does exist at run time. What I suppose I'm trying to say is that a is a constant and b is a variable. Maybe what is wanted is the for the compiler to be "clever" and assume that if you ask for the address of a constant you really want the constant ? -- UUCP: ...!seismo!mcvax!ukc!paisley!rh DARPA: rh%cs.paisley.ac.uk | Post: Paisley College JANET: rh@uk.ac.paisley.cs | Department of Computing, Phone: +44 41 887 1241 Ext. 219 | High St. Paisley. | Scotland. | PA1 2BE
bet@ecsvax.UUCP (Bennett E. Todd III) (03/19/86)
I agree that the inconsistancy between array name semantics and structure name semantics is unfortunate. The extensions of structure assignment, parameter passing by value, and returning by value, are distasteful. Aggregates, both arrays and structures, should not be "automagically" copied around by the compiler; instances of their names as rvalues without explicit dereferencing should be converted to pointers in BOTH cases. Note that (re)establishing the notion that a structure name evaluates to a constant pointer to that structure removes the distinction between the "." and "->" operators for structure member dereference, which removes a popular source of subtle portability bugs (to and from compilers that use the old, simpler semantics). D. Gary Grady (dgary@ecsvax.UUCP) just pointed this out to me, and added that this frees up the operator "->", which we could use for longjmp:-) While I'm yapping about the big steps backward that C has made, let me add the tightening up of the semantics of "goto", making jump tables impossible. Switch statements are ideal for some things; not for everything. If you want to construct efficient finite state automata you need a jump table, without the frills forced on you by the semantics of the switch statement. Let "label" be a new reserved word, for a new data type, not convertable to any other. Let labels in code of the form "<name>:" be constants of type label (and have the compiler do forward referencing correctly, either with multiple passes or with backpatching). Let me declare constant, initialized arrays of type label. Grrhhh. Have to write my own compiler. Grrhhh. Let's call the new language "C--". -Bennett -- Bennett Todd -- Duke Computation Center, Durham, NC 27706-7756; (919) 684-3695 UUCP: ...{decvax,seismo,philabs,ihnp4,akgua}!mcnc!ecsvax!duccpc!bet
garry@batcomputer.TN.CORNELL.EDU (Garry Wiegand) (03/21/86)
In a recent article jsdy@hadron.UUCP (Joseph S. D. Yao) wrote: >... There is no such thing as a pointer to the whole >array: that is a Pasqualische or Fortranian notion. Pointers, in >C, only point to atomic or aggregate (structure/union) objects... Are you sure of this? I sometimes write: foo (ap) register float (*ap)[4][4]; {... (*ap)[0][0] = 33; ...} I do this because my compiler (DEC/Vms) ends up making slightly better use of registers than if I wrote: foo (array) float array[4][4]; {... array[0][0] = 33; ...} (and because it's slightly more pleasing to my brain actually to say "pointer- to-array" if that's what I'm thinking of). Are you saying my syntax is legal only by the grace of DEC? garry wiegand garry%cadif-oak@cu-arpa.cs.cornell.edu
tps@sdchem.UUCP (Tom Stockfisch) (03/21/86)
[] >>>I have noticed that different compilers treat the & operator differently >>>when it is applied to arrays. In particular, the UNIX compiler I have >>>been using warns against it. K&R explicitly deny its legality... >>I agree that it is really a design flaw in the language, to make >>it illegal to form a pointer to an array. & should work on any >>'object'... Joe Yao replies >... >I don't really see what the problem is that people are moaning >about. If you want a pointer to the array, the array name itself >coerces to a pointer containing the memory location at the beginning >of the array. There is no such thing as a pointer to the whole >array: that is a Pasqualische or Fortranian notion. Pointers, in >C, only point to atomic or aggregate (structure/union) objects. I >whole-heartedly agree that for some uses it is rather nice to use >such things. That is why (excuse me while I put on my flak jacket >and asbestos suit) C is not the only language in the world worth >using... C *can* refer to whole arrays. If you really want to take the address of an array rather than just mentioning the array try struct ary { int a[SIZE]; } arr1, arr2; ... &arr1; f(arr1); arr1 = arr2; In this case 'arr1' by itself is not a pointer-constant but represents the whole array (really structure) and '&arr1' refers to a pointer to the whole array. 'arr1.a' is the more familiar pointer-constant pointing to the first element of the array, 'f(arr1)' passes the whole array to the function f(), and 'arr1 = arr2' assigns the whole array. SO WHO NEEDS PASCAL? --Tom Stockfisch, UCSD Chemistry
chris@umcp-cs.UUCP (Chris Torek) (03/21/86)
In article <58@paisley.ac.uk> rh@cs.paisley.ac.uk (Robert Hamilton) takes exception to something in article <211@dg_rtp.UUCP> by throopw@dg_rtp.UUCP (Wayne Throop), who writes: >>I believe that to support reasonable portable code C *must* allow >>the address operator on an array, even if it is not required. Robert says: >Taking the address of an array just doesnt make sense in C. I think you missed the point. Suppose you write the following: #include "../projlib/types.h" x_type variable; f() { g(&variable); ... } g(p) x_type *p; { x_type newvalue; ... *p = newvalue; ... } This looks perfectly reasonable, and works quite well if `x_type' is a name for a simple type, a structure, or a union. It does not work---indeed, it does not even compile---if `x_type' is a name for an array. The problem is that you are not `allowed' to know just what `x_type' really is. As it turns out, it is not often useful to write something like the above if `x_type' is a name for an array, and this problem does not seem to come up in practice---or at least I have not seen it. And if all else fails one can always wrap the array in a structure: typedef struct { int x_val[10]; } x_type; This does seem a bit of a kludge, though. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
greg@utcsri.UUCP (Gregory Smith) (03/21/86)
In article <313@hadron.UUCP> jsdy@hadron.UUCP (Joseph S. D. Yao) writes: >I don't really see what the problem is that people are moaning >about. If you want a pointer to the array, the array name itself >coerces to a pointer containing the memory location at the beginning ^^^^^^ ( right value wrong type. no cigar. ) >of the array. There is no such thing as a pointer to the whole >array: that is a Pasqualische or Fortranian notion. Pointers, in >C, only point to atomic or aggregate (structure/union) objects. Poppycock! char *char_ptr, (*char_ar_ptr)[80]; ++ char_ptr; /* add 1 to the actual value of char_ptr */ ++ char_ar_ptr; /* add _80_ to the actual value of char_ar_ptr */ /* i.e. point to the next array in a list */ IF I can have a pointer to an array, and dereference it to get an array, and increment it to point at the next array, WHY THE $@%@ CAN'T I POINT THE &#&*@&* THING AT AN ARRAY!!!!!!!?????????? ( nicely, I mean ) char line[80]; /* this is what I want to point it at */ char_ar_ptr = &line; /* this should work ... */ char_ar_ptr = line; /* this works, but gets a warning */ /* ( and rightly so ) */ char_ar_ptr = (char(*)[80])line; /* this works (big %$@%# deal) */ Furthermore, I don't buy the argument that array names are really load-time constants. I am mentioning this only because I have heard this argument more than once. I fail to see any logic underlying this; perhaps somebody treated array names as constants in some embryonic implementation of C because it worked for that definition of the language. No excuse. Anyway, array names are not always constants; any array which is local to a function has an address which is relative to the frame pointer. Also, in struct foo{ int foodle; char foo_line[80]; } *foo_ptr; the ARRAY foo_ptr->foo_line doesn't have a constant address, does it? The prosecution rests ( for now ). -- "No eternal reward will forgive us now for wasting the dawn" -J. Morrison ---------------------------------------------------------------------- Greg Smith University of Toronto ..!decvax!utzoo!utcsri!greg
jsdy@hadron.UUCP (Joseph S. D. Yao) (03/22/86)
In article <428@batcomputer.TN.CORNELL.EDU> garry%geology@cu-arpa.cornell.edu.arpa writes: >In a recent article jsdy@hadron.UUCP (Joseph S. D. Yao) wrote: >>... There is no such thing as a pointer to the whole >>array: that is a Pasqualische or Fortranian notion. Pointers, in >>C, only point to atomic or aggregate (structure/union) objects... > >Are you sure of this? I sometimes write: > foo (ap) register float (*ap)[4][4]; {... (*ap)[0][0] = 33; ...} >I do this because my compiler (DEC/Vms) ends up making slightly better >use of registers than if I wrote: > foo (array) float array[4][4]; {... array[0][0] = 33; ...} >(and because it's slightly more pleasing to my brain actually to say "pointer- >to-array" if that's what I'm thinking of). Are you saying my syntax is legal >only by the grace of DEC? > >garry wiegand >garry%cadif-oak@cu-arpa.cs.cornell.edu garry @ cadif-oak or geology: You bring up a good point, and one that I hadn't thought to mention. You are in fact using a pointer to a matrix! Your compiler probably makes different code because you don't say register float array[4][4]; in the second one. (Try it!) I don't understand why your compiler and lint don't complain about your code, though. These two pieces of code are in fact not equivalent in their declarations, though they are the same in effect, as I will explain below. By the way, there are (lots of!) known problems with VMS "C", in terms of what it does versus what all other "C" compilers do. DEC does document most of these; I am not at all sure how thouroughly. The good point is this. Whenever you pass the address of an array, of a n y d i m e n s i o n , as an argument to a function, it comes out on the other side as a pointer. As I mentioned in the last article, this pointer can be looked at as pointing to an object of atomic type, no matter how deeply dimensioned the original array, because all the array is, is a set of objects next to each other in memory. There are no pointers or complex aggregate objects in that memory. This is one way (the machine's way) of looking at it. Another way might be to consider each level of dimensioning an aggregate: so, an array of int [7] is seven ints in a row; and a matrix (2-d array) of int [5][7] is an array of 5 (array of 7 ints in a row)s in a row. Then x[3][4] is the 3*7+4th or 25th int in the row. And then, x is that elusively-sought object, the address of [i.e., a pointer to] an array of 7 ints. BUT, at the same time it is the address of the first int, and the address of an array of 35 ints, and the address of a 5 X 7 matrix of ints! How do we tell the difference? At this point, it might be worth sitting down and drawing a picture of the array, both in X-Y form: x[0][0], x[0][1], ... , x[0][6], x[1][0], ... x[1][6], ... x[4][0], ... x[4][6] and in memory-address order: _x: x[0][0] _x+4: x[0][1] ... _x+136: x[4][6]. Now, obviously, if I coerce x to be an int array, I can also index it from 0 to 34. As mentioned above, whenever one uses an array name as an argument to a function, it gets coerced into a pointer, and must be declared correctly on the other side. For instance, int **x; would be WRONG here: why? ... ... Because, as we said before, there are no pointers here, as there would have to be to have a pointer to a list of pointers. Similarly, int *x[] is WRONG: this also declares a list of pointers, and is equivalent to int **x. The declarations int *x; and int x[]; are also equivalent to each other; and, while they may be used instead of the truth (indexed, as I said, 0 - 34), they are not the truth. Now, int x[5][7]; is the truth. This can, by the way, also be written as int x[][7]; without the compiler objecting, since the compiler does not need to know the first subscript. After all, you can have any number of 7-int arrays pointed to by the passed pointer. Since, as stated above, int *x; and int x[]; are the same, then can anyone see why int x[][7]; and int (*x)[7]; shouldn't be the same? I thought not ... In fact, they are the same. Much to my surprise, we have found the elusive pointer to an array! If I declare int (*x)[7]; I should be able to increment x and get it to point to the next row of seven ints. Well, hush my puppies, it does exactly that! (Cc on 4.2BSD on ISI 68000 Q-bus machine. Cc on Xenix 2.8b on 8086 Altos 986. Cc on Ultrix 1.1 on VAX 11/750. These are the closest machines I can get to on one hop. All agree.) And, in fact, this falls out logically from the language description -- it just is a little-used turn of phrase (as it were). So, what does x[3][4] mean in this context? It means index x by 3, to get the third further row of 7 ints from the one pointed to by x; then take the 4th further int in that row. Or, the 25th int, just as before! Now, why is garry's code wrong? Well, just as we can have a 1-d alias for a 2-d array, so can we have a 3-d alias. And that is exactly what garry has created for us. The declaration: int (*x)[5][7]; is the same as int x[][5][7]. The use of this, as (*x)[3][4], is the same as x[0][3][4]. How do we translate this? Well, x is a pointer to a number of sequential 5X7 matrices. In this sequence of matrices, we are selecting the 0*35+3*7+4th int, or the 25th int. Therefore, the effect is the same, even though we are saying that we are using a 3-d array! In fact, we can take this to as many dimensions as we want. Yes, Virginia, this is confusing. I'm sorry. As I explained last time, it has a little to do with the power of the language, and a lot to do with history. To change it would break a whole lot of existing C programs, which is one of the things that ANSI X3J11 is trying not to do (except for #endif label's, grr grr). And so would should tune our mental models accordingly and learn to live with it. By the way: I can understand not having lint to tell one that the declaration and call in the C program have distinctly different declarations. VMS has been trying to catch up with UNIX in terms of software tools, and seems to be falling rapidly behind. But surely, if you passed an &'d array to a function, a compiler error message something like: "tst.c", line 7: warning: & before array or function: ignored should have come out! Doesn't it? That should tell you something! Disclaimer: any misteaks in the past 130 or so lines are purely the result of my home workstation bottling up this message and squirting it out past midnight so that it looks and feels like I wrote it in my sleep ... The C did compile the way I described, though. No denying it. Pointers to arrays LIVE! -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
ka@hropus.UUCP (Kenneth Almquist) (03/24/86)
> I don't really see what the problem is that people are moaning > about. If you want a pointer to the array, the array name itself > coerces to a pointer containing the memory location at the beginning > of the array. There is no such thing as a pointer to the whole > array: that is a Pasqualische or Fortranian notion. Pointers, in > C, only point to atomic or aggregate (structure/union) objects. Actually, there is such a thing as a pointer to an array in C; otherwise multi-dimensional arrays would not work. For example: int a[5][10]; This declares "a" to be an array of arrays. A reference to "a" is normally converted into a pointer to the first element of "a", and the first element of "a" happens to be an array of 10 integers. Now let's try to do something with a: int (*p)[10]; for (p = a ; p < a + 5 ; p++) {do something;} Some people would prefer to replace "a + 5" with "&a[5]" on stylistic grounds, but the latter is currently illegal because the address of arrays cannot be taken. If we want to have "p" point to a simple array of 10 elements, things get rather awkward: int b[10]; p = ((*)[10])b; This works, but it is not as readable as "p = &b". If we don't want to duplicate the constant "10", the above assignment must be changed to: p = ((*)[sizeof b / sizeof b[0]])b; We cannot write "p = b" because references to "b" are converted to "pointer to int" while "p" is of type "pointer to array[10] of int". To repeat the basic proposal: the conversion of an array expression to a pointer to the first element of the array is inhibited when the "sizeof" operator is applied to an array expression; this conversion could also be inhibited when the "&" operator is applied to an array expression. This would not be a major improvement to the language, but would make certain types of code slightly cleaner. It is a simple extension to C which should not break any existing programs. In fact, the original C compiler written by Dennis Ritchie allowed "&" to be applied to arrays. Kenneth Almquist ihnp4!houxm!hropus!ka (official name) ihnp4!opus!ka (shorter path)
dan@BBN-PROPHET.ARPA (Dan Franklin) (03/24/86)
Even though people have said that the inconsistent treatment of arrays and structures might be a problem from an information-hiding point of view, they've always added that they've never run into it in practice. I'm surprised. I have run into the problem several times in connection with "jmpbuf", the structure (but it's not a structure) that holds the information communicated between setjmp and longjmp. What I've wanted to do in several programs is use setjmp/longjmp to signal exceptions, and sometimes intercept the exception on its way up the stack to do cleanup in some routine. To do this, I make my own temporary copy of the jmpbuf. Unfortunately, I have to know that jmpbuf is an array, not a structure, so that I can write explicit calls to bcopy (or whatever) instead of a simple assignment. To give a concrete example, I might have a low-level memory allocator interface that calls malloc() and does a longjmp() if NULL is returned; this relieves me from the tedious and error-prone testing against NULL everywhere I call malloc(). Then in main() I use setjmp() to set up a handler for the exception, and print a message and exit. But some caller of my allocator might want to gain control for some reason to do cleanup before the program exits. So I would like to write: caller() { jmpbuf temp; temp = memory_failure; /* Wrong */ if (setjmp(memory_failure)) { do_cleanup(); memory_failure = temp; /* Wrong */ longjmp(memory_failure, 1); } code_that_calls_memory_allocator; } Doesn't work, of course. I have to call bcopy instead, or invent my own structure to put the jmpbuf into. And this also means that no matter what some UNIX implementor might want to put into the jmpbuf, it's got to look (to the user) like an array, which is kind of unclean. Dan Franklin
dan@BBN-PROPHET.ARPA (Dan Franklin) (03/24/86)
Bennett E. Todd III (mcnc!ecsvax!duccpc!bet) suggests that structure copying is a bad idea and wants structures to behave like arrays, instead of the reverse as everone else is suggesting. I couldn't disagree more. Having the compiler "automagically" copy structures around for me is perhaps the single most useful capability recently added to C. It vastly simplifies the problems of dealing with data structures. Rob Pike's paper on the organization of the Blit software (in Software Practice and Experience) demonstrates how clean C programming can be given structures that can be passed as arguments and returned. If structures were only referenced by their addresses, using them would be much more painful (as it used to be), since every time you returned one of the damn things you would have to worry about where the storage was coming from. Here's an example adapted from things in Pike's paper: typedef struct { int x, y; } point_t; point_t mk_point(int, int); rectangle_t output; output = mk_rect(mk_point(x,y), mk_point(x + 5, y + 6)) That is, make a rectangle from two points specifying the corners. Try to imagine doing this simple operation in a world in which structures are not copied. The mk_point routine would either have to take a pointer to an empty structure to be filled in as one of its arguments, either returning that same pointer as its return value (so it could be used in cascaded function calls) or return a pointer to an allocated structure that would have to be freed later (so I'd have to capture it as it went flying by in the middle of this expression), or return a pointer to a static structure that was overwritten with each call (which would make this expression impossible, since the same pointer would be returned in both cases). No matter how you slice it, it would be a lot more than two lines of code, and not nearly as clear. Dan Franklin
mike@peregrine.UUCP (Mike Wexler) (03/24/86)
In article <58@paisley.ac.uk> rh@cs.paisley.ac.uk (Robert Hamilton) writes: > >Taking the address of an array just doesnt make sense in C. >You can see the reason if you know why the following bit of >code also won't work: >int a[10]; >int *b; >a=b; /* makes no sense */ true >a+=1; /* ditto */ true >b=a; /* ok of course */ > >The decl. a[10] does 2 things: > 1. reserves storage for 10 elements true > 2. lets the compiler know that "a" is an int * to > of the first element reserved. > It does *not* reserve storage for a pointer to the storage. true Declarations never reserve storage for a pointer to the storage. Your argument doesn't make sense. It would be useful to be able to apply the ampersand operator to any object without knowing what its "real" type is(it could be hiddenn by typedefs). >So "&a" only exists during compilation, in the sense that the >compiler holds the address of the reserved storage somewhere >that "somewhere" has an address at compile time. >The decl. int *b on the other hand does 2 different things. >1. lets the compiler know that "b" is an int * ( for pointer arithmetic) true >2. and reserves a storage location for b. > so &b does exist at run time. wrong. This seems to be your point of confusion. "int *b" reserves space for b that is correct. "b" is a pointer. "&b" is a pointer to that pointer. They are not the same. Here is an example program an the corresponding contents of memory on a hypothetical computer. func() { int i; int *pi int **ppi; i=512; pi=&i; ppi=π return; } address contents use |-----------| 0001 | 0512 | int i; |-----------| 0002 | 0001 | int *pi; |-----------| 0003 | 0002 | int *ppi; |-----------| Note &pi and &ppi are the *CONSTANTS* 2 and 3. Corresponding to the addresses of these variables. Notice never have I said the following construct is legal. &i=pi; This is completely illegal. No compiler I know of will let you do this. > >What I suppose I'm trying to say is that a is a constant and b is a variable. The address of "a" is a constant. The address of "b" is a constant. The contents of both "a" and "b" are variable. It just happens that when you put "a" in your code the c compiler interprets it a &a. The only thing being asked for here is that &a also be a legal syntax for specifying the address of a. > >Maybe what is wanted is the for the compiler to be "clever" >and assume that if you ask for the address of a constant >you really want the constant ? Compilers already do that. All the compilers I know of are "clever" enough to handle the following code. typedef struct foobar FOOBAR; func() { FOOBAR s; FOOBAR *p; p=&s; return; } Yet some compilers can't handle the following code. typedef int FOOBAR[10] func() { FOOBAR s; FOOBAR *p; p=&s; /* should be p=s; */ return; } This(&s) is what is meant by taking the address of an array. It is perfectly reasonable construct. -- Mike Wexler (trwrb|scgvaxd)!felix!peregrine!mike (714)855-3923 All of the preceding opinions are solely those of the author and do not represent the views of any other being, sentient or abstract.
peterc@ecr1.UUCP (Peter Curran) (03/25/86)
Relay-Version: version B 2.10.1 6/24/83; site ecr1.UUCP Path: ecr1!ecrhub!hcrvax!utzoo!watmath!clyde!cbosgd!gatech!seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.lang.c Subject: Re: Address of array Message-ID: <422@umcp-cs.UUCP> Date: Fri, 21-Mar-86 07:04:26 EST Date-Received: Tue, 25-Mar-86 04:33:12 EST References: <750@abic.UUCP> <211@dg_rtp.UUCP> <685@steinmetz.UUCP> <58@paisley.ac.uk> Organization: U of Maryland, Computer Science Dept., College Park, MD Lines: 53 Chris Torek writes (in reply to Robert Hamilton's reply to Wayne Throop): > I think you missed the point. Suppose you write the following: > > #include "../projlib/types.h" > > x_type variable; > > f() > { > g(&variable); > ... > } > > g(p) > x_type *p; > { > x_type newvalue; > > ... > *p = newvalue; > ... > } > > This looks perfectly reasonable, and works quite well if `x_type' > is a name for a simple type, a structure, or a union. It does not > work---indeed, it does not even compile---if `x_type' is a name > for an array. The problem is that you are not `allowed' to know > just what `x_type' really is. > > As it turns out, it is not often useful to write something like > the above if `x_type' is a name for an array, and this problem does > not seem to come up in practice---or at least I have not seen it. > And if all else fails one can always wrap the array in a structure: > > typedef struct { > int x_val[10]; > } x_type; This situation does occur - in connection with longjmp/setjmp. The functions are passed a variable of type 'jmp_buf'. In fact, the functions expect an address. With most compilers, 'jmp_buf' is an array, and naming it produces an address. On a few compilers, the 'jmp_buf' is a structure (which makes more sense), but you must pass its address (i.e. using the '&' operator). One more portability hiccup. -- Peter Curran Emerald City Research, Ltd. ...utzoo!ecrhub!ecr1!peterc
chris@umcp-cs.UUCP (Chris Torek) (03/26/86)
In article <2377@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: > char *char_ptr, (*char_ar_ptr)[80]; > ++ char_ptr; /* add 1 to the actual value of char_ptr */ > ++ char_ar_ptr; /* add _80_ to the actual value of char_ar_ptr */ > /* i.e. point to the next array in a list */ Yes. > char line[80]; /* this is what I want to point it at */ > char_ar_ptr = &line; /* this should work ... */ Debatable. This works, and is probably even what you `really' mean: #define N 2 /* e.g. */ char lines[N][80]; char_ar_ptr = lines; If you only have one line, why do you need to point at a set of lines? -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
levy@ttrdc.UUCP (Daniel R. Levy) (03/26/86)
In article <150@sdchema.sdchem.UUCP>, tps@sdchem.UUCP (Tom Stockfisch) writes: >[] >Joe Yao replies >>I don't really see what the problem is that people are moaning >>about. If you want a pointer to the array, the array name itself >>coerces to a pointer containing the memory location at the beginning >>of the array. There is no such thing as a pointer to the whole >>array: that is a Pasqualische or Fortranian notion. 'Scuse me, can somebody educate me as to why that would be a "Fortranian" (I withhold opinion on the Pascal allegation) notion? I was under the impression that most, if not all, Fortrans implement array references pretty much the same way that C does: by reference to the address of the first element in the array, with offsets computed according to the subscripts and then automatically dereferenced for use. The only differences I could see is in argument passing where C can pass things by value, whereas Fortran must pass by reference. FORTRAN C INTEGER I(1000) <--> int i[1000]; J = I(50) <--> int j = i[49]; I(3) = 8 <--> i[2] = 8; CALL FOO(I) <--> foo(i); /* pass address of first element */ CALL FOO(I(3)) <--> foo(&i[2]); /* or of another? */ ... ... SUBROUTINE FOO(K) <> foo(k) /* and dereference on the "other side" */ INTEGER K(1000) int k[1000]; { WRITE(*,*)K(3) printf("%d\n",k[2]); ... ... END } -- ------------------------------- Disclaimer: The views contained herein are | dan levy | yvel nad | my own and are not at all those of my em- | an engihacker @ | ployer or the administrator of any computer | at&t computer systems division | upon which I may hack. | skokie, illinois | -------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa, vax135}!ttrdc!levy
jsdy@hadron.UUCP (Joseph S. D. Yao) (03/27/86)
In article <2377@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: a very clear exposition of where I went wrong when I said: >> There is no such thing as a pointer to the whole >>array: that is a Pasqualische or Fortranian notion. Pointers, in >>C, only point to atomic or aggregate (structure/union) objects. up to the point where he slips off the track: > Anyway, array names >are not always constants; any array which is local to a function has an address >which is relative to the frame pointer. Also, in > struct foo{ int foodle; char foo_line[80]; } *foo_ptr; >the ARRAY foo_ptr->foo_line doesn't have a constant address, does it? Well ... this is true, but only the sense that a n y address is relative to the address space in which it lives. Something is not a constant if it can be changed, right? But you cannot say: foo_ptr->foo_line++ or { int x[XSIZ]; x++; } Despite the fact that I stupidly said there ain't no array pointers (and I should know better, I've found where I'd written otherwise!), I still insist that, the way C treats them right now, the model for arrays is a pointer constant. In stack and struct, this translates to a pointer constant o f f s e t . -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
greg@utcsri.UUCP (Gregory Smith) (03/28/86)
In article <530@umcp-cs.UUCP> chris@umcp-cs.UUCP (Chris Torek) writes: >In article <2377@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: > >> char (*char_ar_ptr)[80]; >> ...[ a pointer to array of char ] >> >> char line[80]; /* this is what I want to point it at */ > >> char_ar_ptr = &line; /* this should work ... */ > >Debatable. ( obviously! ) > >This works, and is probably even what you `really' mean: > > #define N 2 /* e.g. */ > char lines[N][80]; > > char_ar_ptr = lines; > >If you only have one line, why do you need to point at a set of >lines? Good point ... I actually hadn't thought of it exactly that way. Two answers come to mind, though: (1) Because it is there. :-) (2) Suppose the array 'lines' is actually more than two: char lines[10][80]; Suppose I want to point char_ar_ptr at lines[i] ( a perfectly reasonable thing to want to do ): This is allowed: char_ar_ptr = lines + i; /* let's really confuse those novices! >:-) */ This isn't: char_ar_ptr = &lines[i]; /* pointer to the ith array */ So &a[b] is not equivalent to a+b here. What a shame. I like using &a[b] in general, and ALWAYS use it when 'a' is an array as opposed to a pointer. Too bad I can't... especially when there's no good reason for not being able to. -- "Everything under the sun is tune, but the sun is eclipsed by the moon" - PF ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
jsdy@hadron.UUCP (03/31/86)
In article <807@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes: >In article <150@sdchema.sdchem.UUCP>, tps@sdchem.UUCP (Tom Stockfisch) writes: >>[] >>Joe Yao replies >>>array: that is a Pasqualische or Fortranian notion. > >'Scuse me, can somebody educate me as to why that would be a "Fortranian" Dan, I've already recanted that whole posting. It was written after midnight or something [;-}]. What I think I meant was that Fortran, like Pascal, allows you to declare an object to be of a certain size; and the functions that operate on it know what that size was. Compare this to C, where you have to explicitly declare what the object you're pointing to is, before knowing its size. Then you can declare a pointer to the first of a sequence of arrays of a given size. Fortran doesn't even have pointers anyway. (*sigh*) -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
aglew@ccvaxa.UUCP (03/31/86)
struct and array pass-by-value and return - a moderate view: Structures should always be passed by reference. Usually you only need to look at fields, and if you need scratch space then you should declare local variables. (Modify this for structs that fit in small packages, like struct { short x,y; }). However, being able to return structs without having to worry about allocating space is a great convenience. Actually, what is needed is return of pointers, with a convenient way of automatically allocating space for the struct that you're going to point to. This way you get convenience and the efficiency of not having all those extra copies to and from the stack. Doesn't everybody use a `statalloc' package for this type of thing? Structure and array assignment, and comparison for equality, without buffer copies is a good thing.
greg@utcsri.UUCP (Gregory Smith) (03/31/86)
This is a repost - sorry if you've seen it, but it 'bounced', so I'm sending it again. ( How can news bounce? The stuff attached to the returned news ( presumably explaining the reason ) was greek to me... ) In article <530@umcp-cs.UUCP> chris@umcp-cs.UUCP (Chris Torek) writes: >In article <2377@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes: > >> char (*char_ar_ptr)[80]; >> ...[ a pointer to array of char ] >> >> char line[80]; /* this is what I want to point it at */ > >> char_ar_ptr = &line; /* this should work ... */ > >Debatable. ( obviously! ) > >This works, and is probably even what you `really' mean: > > #define N 2 /* e.g. */ > char lines[N][80]; > > char_ar_ptr = lines; > >If you only have one line, why do you need to point at a set of >lines? Good point ... I actually hadn't thought of it exactly that way. Two answers come to mind, though: (1) Because it is there. :-) (2) Suppose the array 'lines' is actually more than two: char lines[10][80]; Suppose I want to point char_ar_ptr at lines[i] ( a perfectly reasonable thing to want to do ): This is allowed: char_ar_ptr = lines + i; /* let's really confuse those novices! >:-) */ This isn't: char_ar_ptr = &lines[i]; /* pointer to the ith array */ So &a[b] is not equivalent to a+b here. What a shame. I like using &a[b] in general, and ALWAYS use it when 'a' is an array as opposed to a pointer. Too bad I can't... especially when there's no good reason for not being able to. -- "If you aren't making any mistakes, you aren't doing anything". ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
rh@cs.paisley.ac.uk (Robert Hamilton) (04/01/86)
In article <260@peregrine.UUCP> mike@peregrine.UUCP (Mike Wexler) writes: >In article <58@paisley.ac.uk> rh@cs.paisley.ac.uk (Robert Hamilton) writes: >> >>Taking the address of an array just doesnt make sense in C. >>You can see the reason if you know why the following bit of >>code also won't work: >>int a[10]; >>int *b; >>a=b; /* makes no sense */ >true >>a+=1; /* ditto */ >true >>b=a; /* ok of course */ >> >>The decl. a[10] does 2 things: >> 1. reserves storage for 10 elements >true >> 2. lets the compiler know that "a" is an int * to >> of the first element reserved. >> It does *not* reserve storage for a pointer to the storage. >true >Declarations never reserve storage for a pointer to the storage. Your argument >doesn't make sense. >It would be useful to be able to apply the ampersand operator to any object >without knowing what its "real" type is(it could be hiddenn by typedefs). > >>So "&a" only exists during compilation, in the sense that the >>compiler holds the address of the reserved storage somewhere >>that "somewhere" has an address at compile time. >>The decl. int *b on the other hand does 2 different things. >>1. lets the compiler know that "b" is an int * ( for pointer arithmetic) >true >>2. and reserves a storage location for b. >> so &b does exist at run time. >wrong. This seems to be your point of confusion. "int *b" reserves space for >b that is correct. "b" is a pointer. "&b" is a pointer to that pointer. They >are not the same. NO you misunderstand me. My argument is a valid explanation of why C rejects the address of an array (at least in my interpretation of what EXISTS means) If storage is reserved for b then that storage must have a runtime address must it not ?? And so that address is &b and can be taken as rhs. You say so yourself : >int *pi; >int **pi=π /**/ I don't of course mean that &b is some value sitting somewhere in memory so you cant take the &b as a lhs .(as you say) In the same way (int a[10]) sits in memory somewhere and has an address a so you can say int *b=a which also happens to be &a[0]. But a itself does not sit in memory (as b does) and so &a does not exist. The pointer/array confusion comes because C takes a to be the address of the array rather than the array itself, which is inconsistent with the treatment of everything else. But enough of this, I do see the problem and agree... -- UUCP: ...!seismo!mcvax!ukc!paisley!rh DARPA: rh%cs.paisley.ac.uk | Post: Paisley College JANET: rh@uk.ac.paisley.cs | Department of Computing, Phone: +44 41 887 1241 Ext. 219 | High St. Paisley. | Scotland. | PA1 2BE
guy@sun.uucp (Guy Harris) (04/03/86)
> struct and array pass-by-value and return - a moderate view: > Structures should always be passed by reference. Usually you only need > to look at fields, and if you need scratch space then you should declare > local variables. (Modify this for structs that fit in small packages, > like struct { short x,y; }). For efficiency reasons yes, they should be passed by reference in many circumstances. However, the language already supports call-by-value, and it can be convenient in many other circumstances, so use or non-use of call-by-value should be a matter of programming style, not of language definition. > Structure and array assignment, and comparison for equality, without buffer > copies is a good thing. You are aware, of course, that comparison for equality of structures, assuming it were added to the language, could not be implemented by a "string compare" instruction or code sequence? Such a sequence would compare the padding bytes between structure members; there is no guarantee that those bytes are ever initialized, so two structures whose values are equal may not contain identical bit patterns. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa (yes, really)
rbj%icst-cmr@smoke.UUCP (04/05/86)
> Structure and array assignment, and comparison for equality, without buffer > copies is a good thing. You are aware, of course, that comparison for equality of structures, assuming it were added to the language, could not be implemented by a "string compare" instruction or code sequence? Such a sequence would compare the padding bytes between structure members; there is no guarantee that those bytes are ever initialized, so two structures whose values are equal may not contain identical bit patterns. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa (yes, really) Fisrt, I disagree that struxure (or array) assignments are A Good Thing. I much prefer the model of limiting primitive data types to values that can be held in a register on an idealized machine. So much for the `religious' part. Secondly, struxures could be created with the padding bytes set to all zero bits. Then, any garbage appearing in them could only be creating by sloppy coding practices which even *I* abhor, even considering my widely known nonportable tendencys. (Root Boy) Jim Cottrell <rbj@cmr>
sbs@valid.UUCP (Steven Brian McKechnie Sargent) (04/17/86)
> In article <260@peregrine.UUCP> mike@peregrine.UUCP (Mike Wexler) writes: > >In article <58@paisley.ac.uk> rh@cs.paisley.ac.uk (Robert Hamilton) writes: > >> > >> (Much flamage about "right" way to interpret cettes choses) > > (Much flamage about "right" way to interpret cettes choses) > (Much flamage about "right" way to interpret cettes choses) The ANSI debate on the C standard, which has devolved into a wide variety of entertaining circuses, recently had a sidelight into the &array issue. When I last left it, the committee was leaning toward allowing &array so that programmers could portably declare and use thusly: typedef int time_t[2]; ... time_t t; printf("%s", (time(&t), ctime(&t))); (This objection is rather neatly removed by typedef struct { int once_upon_a[2]; } time_t; but never mind. ) I lean in the opposite direction (I believe that &array is an undesirable construct) because of the following gotcha: char a[200][40]; char *b[200]; ... strcpy(b[i], a[i]); /* works */ strcpy(b[i], &a[i]); /* works */ strcpy(&b[i], &a[i]); /* don't work */ Of course, adherents to strong typing will say, "Thou fool. Declare strcpy(char *, char *) in thy headers," and they're perfectly entitled to their opinions. S.
sam@delftcc.UUCP (Sam Kendall) (04/18/86)
In article <227@valid.UUCP>, sbs@valid.UUCP writes: > When I last left it, the [ANSI] committee was leaning toward allowing &array > so that programmers could portably declare and use thusly: > > typedef int time_t[2]; > ... > time_t t; > printf("%s", (time(&t), ctime(&t))); The point is uniformity of reference, or, more specifically, freeing the programmer from (some) worrying about what type underlies a typedef. In this case, if you want to get a pointer to a variable, you shouldn't have to worry about whether the variable is an array or not, you should just be able to say, for variable `v', `&v'. Total uniformity of reference is impossible for arrays, of course, but allowing address-of-array brings the language a bit closer. > (This objection is rather neatly removed by > > typedef struct { > int once_upon_a[2]; > } time_t; > > but never mind. > ) This won't work for jmp_buf, which must be an array in order to allow calls with the documented syntax, for jmp_buf jb, `setjmp(jb)'. > I lean in the opposite direction (I believe that &array is an undesirable > construct) because of the following gotcha: > > char a[200][40]; > char *b[200]; > ... > strcpy(b[i], a[i]); /* works */ > strcpy(b[i], &a[i]); /* works */ > strcpy(&b[i], &a[i]); /* don't work */ > > Of course, adherents to strong typing will say, "Thou fool. Declare > strcpy(char *, char *) in thy headers," and they're perfectly entitled > to their opinions. No, they'll say, "Use lint, and you will find that only the first strcpy is correct." Lint complains about the last two. Your gotcha is only a gotcha if you don't use lint, in which case there are millions of other gotchas. ---- Sam Kendall { ihnp4 | seismo!cmcl2 }!delftcc!sam Delft Consulting Corp. ARPA: delftcc!sam@NYU.ARPA
gwyn@BRL.ARPA (04/21/86)
typedef struct { whatever-you-need } jmp_buf[1]; solves the problem of the way setjmp()'s parameter is used, with completely type-correct implementation (in the "whatever-you-need" part). Too bad setjmp() was defined as taking an array parameter in the first place.
greg@utcsri (04/25/86)
In article <153@brl-smoke.ARPA> gwyn@BRL.ARPA writes: >typedef struct { whatever-you-need } jmp_buf[1]; > >solves the problem of the way setjmp()'s parameter is used, >with completely type-correct implementation (in the >"whatever-you-need" part). Too bad setjmp() was defined >as taking an array parameter in the first place. I've been wondering about this... Why would you need to define jmp_buf as a structure? It seems (1) it is impossible to write setjump or longjmp in C (2) the contents of the buffer are completely non-portable, so any program that looks at or alters them is non-portable (3) you can't do anything useful with them anyway, from C. All jmp_buf is is a certain amount of space, as far as C needs to be concerned. I think point (3) is a bit shaky - the contents just might be useful in certain inherently non-portable code. And it would be nice, I agree, if jmp_buf had been defined as a structure - if only to allow easy copying of jmp_buf records. A definition might look like `typedef struct{ char *dummy[11];} jmp_buf;'. But are there cases where a structure was used out of necessity? -- "For every action there is an equal and opposite malfunction" ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg