friedl@vsi.UUCP (Stephen J. Friedl) (02/28/88)
Netlanders, I've had an idea for C for a long time and would like to see what you people think of it and whether it is worthy of submis- sion to the standardardization committee. I ran this by Doug Gwyn and he seems to think it's plausible. Your comments -- pro or con -- would really be appreciated. It no strong objections are raised I'll submit it to the committee. This new item might be called "structure literals" (thanks to Doug for the name). Basically, let's say that I want to have a structure foo: struct foo { char *name; int age; }; Initializing a table of these is obvious, but what about statically initializing a table of *pointers* to structures? I need to have two tables, the first of which is probably hidden from the rest of the world. struct foo _table[] = { { "Bill", 25 }, { "Jim", 10 }, { "Bob", 40 } }; struct foo *table[] = { &_table[0], &_table[1], &_table[2], }; This is really a bummer to maintain without special kinds of preprocessors and it strikes me as something that the compiler should be able to handle in a straightforward manner. I propose something like: struct foo *table[] = { & { "Bill", 25 }, & { "Jim", 10 }, & { "Bob", 40 }, }; Where the compiler sees the & before the {initializer}, puts the {struct} somewhere and throws the pointer into the table. Note: The & { } notation is just something I thought up off the top of my head -- alternate ideas are welcome. I hope I am not name-dropping or putting Doug on the spot, but he had some really good ideas on this: "I would suggest generalizing the notion to include structure literals as the source for assignment state- ments, too, which would probably be best done by adding 'struct-literal' to the a new section 'Structure literals' inserted after 3.1.4 ('String literals') that describes the syntax and semantics of struct-literal (much like the syntax of the { ... } part of a struct de- clarator, except contain only constants, string literals, and struct literals)." [end comments from Doug] I guess the general mechanism would allow: main() { struct foo x, *xp; x = { "Bill", 12 }; xp = & { "Bill", 12 }; This undoubtedly bring up a whole host of questions: can we pass structure-literals as arguments to functions? Can we cast them? Return them from functions? There are probably lots more. I don't have a copy of the current draft but will be picking one up on Monday and seeing where these all fit in. I would really like it if you wizards could comment on this idea: would it be helpful? Can it be specified in the language cleanly? Can a compiler handle it cleanly? Thanks much, Steve -- Life : Stephen J. Friedl @ V-Systems, Inc/Santa Ana, CA *Hi Mom* CSNet: friedl%vsi.uucp@kent.edu ARPA: friedl%vsi.uucp@uunet.uu.net uucp : {kentvax, uunet, attmail, ihnp4!amdcad!uport}!vsi!friedl
flaps@dgp.toronto.edu (Alan J Rosenthal) (02/28/88)
In article <56@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: > struct foo *table[] = { > & { "Bill", 25 }, > & { "Jim", 10 }, > & { "Bob", 40 }, > }; > > Where the compiler sees the & before the {initializer}, it puts >the {struct} somewhere and throws the pointer into the table. This is good. It is an analogue of what happens with strings. It would be good to extend this to arrays and other things. For example, why not be able to write "&3" to get a pointer to int which points to a 3? (This is currently achievable by the non-portable (int *)"\0\0\0\003".) The basic advantage of this is it reduces the need for temporary variables, which are generally a Bad Thing. This is not as bad an addition as some of the ANSI things because there is semi-precedent with strings. Unfortunately, this doesn't seem to allow creating, say, a short in this manner, because you can't specify shorts in expressions. Any attempt to fix this would probably be a very bad addition (such as differentiating "&(short)3" from "&3" even though "(short)3" and "3" usually are identical). (Of course, they're already different when sizeof is used on them, but this is already ugly.) ajr -- If you had eternal life, would you be able to say all the integers?
wesommer@athena.mit.edu (William Sommerfeld) (02/29/88)
In article <56@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: >Netlanders, > > I've had an idea for C for a long time ... >... This new item might be called "structure literals" (thanks >to Doug for the name). Richard Stallman's GCC implements an extension of this as a language extension. This is how he documents it (this is from the file "internals.texinfo" from the GNU CC distribution; it is covered by the GNU copyleft); I'm not sure I like the syntax, but it's better than nothing. * Constructor expressions are allowed. A constructor looks like a cast containing an initializer. Its value is an object of the type specified in the cast, containing the elements specified in the initializer. The type must be a structure, union or array type. As explained above, GNU C does not require the elements of the initializer to be constant. Assume that `struct foo' and `structure' are declared as shown: struct foo {int a; char b[2];} structure; Here is an example of constructing a `struct foo' with a constructor: structure = ((struct foo) {x + y, 'a', 0}); This is equivalent to writing the following: { struct foo temp = {x + y, 'a', 0}; structure = temp; } You can also construct an array. A constructed array is not an lvalue and therefore cannot be coerced into a pointer to its first element. As a consequence, the only valid way to use a constructed array is to subscript it. Here is an example of constructing an array of three elements and then choosing one of them: output = ((int[]) { 2, x, 28 }) [input];
franka@mmintl.UUCP (Frank Adams) (03/02/88)
In article <1988Feb28.130526.4147@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes: >Unfortunately, this doesn't seem to allow creating, say, a short in >this manner, because you can't specify shorts in expressions. Any >attempt to fix this would probably be a very bad addition. There is an obviously correct way to permit specification of short constants: append an s. Exactly analogous to appending an l for long constants. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
karl@haddock.ISC.COM (Karl Heuer) (03/02/88)
In article <1988Feb28.130526.4147@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes: >In article <56@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: >> struct foo *table[] = { >> & { "Bill", 25 }, >> & { "Jim", 10 }, >> & { "Bob", 40 }, >> }; > >This is good. It is an analogue of what happens with strings. It would be >good to extend this to arrays and other things. For example, why not be able >to write "&3" to get a pointer to int which points to a 3? (I'll use backquotes `` in running text to avoid colliding with C notation.) I like the concept of unnamed remote objects, but I'm uneasy about allowing `&` to apply to a non-lvalue. I would prefer a more explicit syntax: let's postulate a keyword `remote` that looks like a function call with two arguments, the first of which is a type name, and the second an initializer; the result is an unnamed lvalue of the specified type and value. Thus, instead of `&3` we write `&remote(int, 3)`. The struct example would use `&remote(struct foo, {"Bill", 25})`. The existing notation for string literals can now be described in terms of remotes: `"foo"` is synonymous with `&remote(char[4], {'f', 'o', 'o', '\0'})`. (All remotes, like strings in ANSI C, should be non-writable and poolable at the implementor's discretion.) This syntax is less kludgy than the other proposals I've seen, and by making the type explicit we avoid the ambiguities. Unfortunately it's a bit verbose. It could be changed from an alphabetic operator to punctuation, but I suspect the need is sufficiently rare that the longer name is acceptable. >Of course, [`3` and `(short)3` are] already different when sizeof is used ... Only on a broken compiler. In C, `sizeof((short)3)` returns sizeof(int). (Because `(short)3` is not an lvalue.) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
tada@athena.mit.edu (Michael Zehr) (03/02/88)
In article <1988Feb28.130526.4147@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes: >This is good. It is an analogue of what happens with strings. It would be >good to extend this to arrays and other things. For example, why not be able >to write "&3" to get a pointer to int which points to a 3? Actually, VAX C 2.2 allows this, although it's completely non-portable, of course. ------- michael j zehr "My opinions are my own ... as is my spelling."
ian@puivax.UUCP (Ian Wilson) (03/03/88)
In article <2804@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >In article <1988Feb28.130526.4147@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes: >>In article <56@vsi.UUCP> friedl@vsi.UUCP (Stephen J. Friedl) writes: >>> struct foo *table[] = { >>> & { "Bill", 25 }, >> > >(I'll use backquotes `` in running text to avoid colliding with C notation.) > >I like the concept of unnamed remote objects, but I'm uneasy about allowing >`&` to apply to a non-lvalue. I would prefer a more explicit syntax: let's >postulate a keyword `remote` that looks like a function call with two >arguments, the first of which is a type name, and the second an initializer; >the result is an unnamed lvalue of the specified type and value. Thus, >Only on a broken compiler. In C, `sizeof((short)3)` returns sizeof(int). >(Because `(short)3` is not an lvalue.) Another place where anonymous objects would be handy is for functions embedded in data structures. For example: struct { char *name; int (*handler)(); } table[] = { {"fred", &remote( int (*)(), { return 6; }}, -- etc --- }; These functions have similar properties to the struct example originally quoted: their names are never needed, they have to be constructed somewhere distant from where they are required, their names must be chosen so as not to conflict with anything else, and so on. Presumably, in order to be able to specify formal parameters to these anonymous functions the `remote' syntax would have to be extended: (*(&remote( (*)(char * x), {printf("%s\n", x);} ))); Perhaps it would be better to acknowledge what `remote' is trying to be and call it `lambda' .... (:-)) ian wilson
henry@utzoo.uucp (Henry Spencer) (03/04/88)
The only specific problem I see with this scheme is that there is no specific indication of the type of the structure literals. This is unwise; there are situations where it's not trivial to guess from context. There is also a more general problem. To approximate the probable response of X3J11: "Need not convincingly shown; existing constructs can be used to same effect; lack of implementation experience in C." -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/04/88)
In article <1988Mar3.183939.945@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >There is also a more general problem. To approximate the probable response >of X3J11: "Need not convincingly shown; existing constructs can be used to >same effect; lack of implementation experience in C." I think a good case could be made for some such facility. Whether an argument sufficient to convince X3J11 to change the proposed standard at this late date could be found is the real question. If the idea is sent in as a public comment, it needs to have a convincing argument attached.
decot@hpisod2.HP.COM (Dave Decot) (03/05/88)
> There is also a more general problem. To approximate the probable response > of X3J11: "Need not convincingly shown; existing constructs can be used to > same effect; lack of implementation experience in C." Aggregate constants are needed for data abstraction. The problem of deciding what their type is solved for now (and possibly always) by stating in the standard that such syntax has no inherent type and must be cast or assigned to the desired type. Dave Decot hpda!decot
henry@utzoo.uucp (Henry Spencer) (03/06/88)
> >... "Need not convincingly shown; existing constructs can be used to > >same effect; lack of implementation experience in C." > > I think a good case could be made for some such facility... Um, Doug, please explain how said good case would refute any, let alone all, of the three objections I cited. Note that the first objection says "need", not "wish". For heaven's sake, have we forgotten that X3J11's supposed mission was to *standardize* C, not redesign it?!? -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
henry@utzoo.uucp (Henry Spencer) (03/06/88)
> Aggregate constants are needed for data abstraction. I guess I'm simple-minded; you'll have to explain in more detail. I use data abstraction routinely and have never *needed* aggregate constants. I also find it difficult to envision a situation in which it would be impossible to write static const struct thingie xxx = { ... }; ... foo = xxx; instead of foo = { ... }; It is agreed that the latter form is more convenient. But we were talking about *needs*, in the context of an existing language, not about a wishlist for a new language. > The problem of deciding what their type is solved for now (and possibly > always) by stating in the standard that such syntax has no inherent type > and must be cast or assigned to the desired type. [expletive deleted] Speaking as a user and an implementor, this is an abortion if there ever was one. If one *must* add aggregate constants to the language -- preferably as an experimental variant and not as part of the effort to STANDARDIZE THE CURRENT LANGUAGE, DAMMIT! -- then the right way to do it is probably the GNU compiler's approach, which avoids this hideous botch entirely. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/07/88)
In article <1988Mar5.213746.12022@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >> >... "Need not convincingly shown; existing constructs can be used to >> >same effect; lack of implementation experience in C." >> I think a good case could be made for some such facility... >Um, Doug, please explain how said good case would refute any, let alone >all, of the three objections I cited. Note that the first objection says >"need", not "wish". For heaven's sake, have we forgotten that X3J11's >supposed mission was to *standardize* C, not redesign it?!? I meant that I think it could be reasonably argued that there IS a need for such a facility. In its absence, we've been resorting to kludges using "awk" scripts and such to help build initializer tables as separate files which are then #included at compile time. This requires introducing a lot of unique struct names that are of no value to the programmer other than part of the workaround. It is embarrassing to admit that this could have been solved by adjusting the language design, but wasn't. If you haven't run into this problem, consider yourself fortunate. It isn't absolutely necessary to have had previous implementation experience with a proposed feature, if it is clear to everyone how it would be implemented and what the consequences would be. Certainly, just because a feature is a "nice idea" is not sufficient reason to toss it into the standard, but when an idea solves an existing real programming problem in a clean way it is worth considering. Part of the charter of X3J11, apart from standardizing the common part of existing practice, is to find fixes for problems in existing practice. (If existing practice were free of problems, there would be no need for a standard!) At this point my feeling is that X3J11 will not want to add any more "features" to the language, since they're trying to get the final standard published as soon as possible. However, if an extremely strong case can be made for a new proposal, I'm sure it will still receive serious consideration.
decot@hpisod2.HP.COM (Dave Decot) (03/07/88)
I write: > > Aggregate constants are needed for data abstraction. Henry Spencer responds: > I guess I'm simple-minded; you'll have to explain in more detail. I use > data abstraction routinely and have never *needed* aggregate constants. In this sense of "need", we obviously don't "need" strong typing prototypes or "const" specifiers, either, since we have managed to limp along without them for quite a long time. See below for my explanation of a situation greatly simplified by the ability to treat structures and arrays as if they were actually manipulable objects instead of "special" things deserving special attention. I fail to see that the committee has drawn and observed "need" as a clear boundary for what should be standardized. > I also find it difficult to envision a situation in which it would be > impossible to write > > static const struct thingie xxx = { ... }; > ... > foo = xxx; > > instead of > > foo = { ... }; It isn't "impossible", obviously, but it makes it impossible for me to provide a library involving such constants that would permit applications to use values of that type as initializers without knowing whether it was a structure type. The support of aggregate constants would provide the ability to change the representation of small abstract 'magic cookie' types from integer types to more complicated types as the system evolves. For instance, we could have declared signal's second argument action_t, and later changed it from an integer to a structure without having to introduce sigvec() (or sigaction()) to support more complicated arguments. For another instance, suppose I would like to be able to make clock_t or dev_t a structure type (since the longest portable integral type is "long"), and I would like to provide some constants of those types as part of an interface to application library routines that use them. At the moment, these constants would only work correctly in initializers. > > The problem of deciding what their type is solved for now (and possibly > > always) by stating in the standard that such syntax has no inherent type > > and must be cast or assigned to the desired type. > > [expletive deleted] Speaking as a user and an implementor, this is an > abortion if there ever was one. Thank you for the feedback. But I wonder if you would be so kind as to elaborate on this comment, unless it would dangerously elevate your blood pressure. :-) I'm afraid it is not clear to me that all usages of structure constants are self-explanatory. I intended the above restriction to be a restriction on portable applications to make it EASIER for implementations to determine what to do with inline aggregate constants. It also turns out that casts would seldom be necessary under the given restriction. I'm also not really intending that the standard should preclude implementations that manage to figure it out. It would be fine if I didn't have to cast the constants to the right type and the compiler could figure out that "func({13, 0, 0})" was passing a constant of type "struct wow {unsigned short int x; char *foo; char bar;}" without help, but I think code taking advantage of that relaxation would be harder to read and I'd add the (struct wow) cast anyway. > preferably as an experimental variant and not as part of > the effort to STANDARDIZE THE CURRENT LANGUAGE, DAMMIT! Whatever you like. I just thought it would be neat if it would work the same way in all implementations that decide to provide this natural extension. >-- then the right > way to do it is probably the GNU compiler's approach, which avoids this > hideous botch entirely. I wonder if you would mind summarizing that approach for those of us who don't have access to that compiler's source code. At any rate, your comment seems to imply that this is existing practice, so I am having trouble seeing why this is a topic that should not be standardized. Thanks. Dave Decot hpda!decot
flaps@dgp.toronto.edu (Alan J Rosenthal) (03/07/88)
I, flaps@dgp.toronto.edu (Alan J Rosenthal), wrote: >>... because you can't specify shorts in expressions. Any >>attempt to fix this would probably be a very bad addition. In article <2743@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >There is an obviously correct way to permit specification of short >constants: append an s. Exactly analogous to appending an l for long >constants. Not very analogous to appending an L for long constants. Quite analogous to appending an F for floating constants, as in the (current) ansi draft. It requires doing away with default promotion rules, as they have for float -> double. Your method of specifying shorts would generate ints, just as (short)3 now does. ajr -- If you had eternal life, would you be able to say all the integers?
karl@haddock.ISC.COM (Karl Heuer) (03/09/88)
In article <139@puivax.UUCP> ian@puivax.UUCP (Ian Wilson) writes: >Another place where anonymous objects would be handy is for functions >embedded in data structures. For example: ... > (*(&remote( (*)(char * x), {printf("%s\n", x);} ))); Actually, to be consistent with my proposal the first operand of `remote` should be the type of the object, not of the pointer. Thus remote( void (char *x), {printf("%s\n", x);} ) would be equivalent to mentioning the (non-existent) name of the remote function, hence this gives you a function pointer without using "&". (As has been pointed out to me by e-mail, I made this mistake in my char[] example.) Using it as above would allow you to stuff it into a function table; or you could invoke it via remote( void (char *x), {printf("%s\n", x);} )("hello, world"); Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
flaps@dgp.toronto.edu (Alan J Rosenthal) (03/09/88)
decot@hpisod2.HP.COM (Dave Decot) wrote: >The problem of deciding what their type is solved for now (and possibly >always) by stating in the standard that such syntax has no inherent type >and must be cast or assigned to the desired type. henry@utzoo.uucp (Henry Spencer) responded: >[expletive deleted] Speaking as a user and an implementor, this is an >abortion if there ever was one. decot@hpisod2.HP.COM (Dave Decot) responded: >Thank you for the feedback. But I wonder if you would be so kind as to >elaborate on this comment ... >I'm afraid it is not clear to me that all usages of structure constants >are self-explanatory. They're not, but the point is that this is a totally new meaning for a cast. Usually, a cast is a unary operator. Here, it's part of the description, like a declaration. To be specific: "(int)f" is an expression that gets an int-ish value for the floating expression f. It doesn't change f. In your proposal, (struct a){...} and (struct b){...} imply different values for {...}. This is very inconsistent, even worse than the inconsistencies between casting pointers and casting numerical types. Also, your (struct ..) cast will produce an lvalue, which is also a big inconsistency. I think it's clear that a new syntax, such as Karl Heuer's, is required. I would prefer a symbol rather than a keyword, but that's just me. (But: how about any of backquote, dollar, at (@), or right square bracket? Perhaps unary comma? Perhaps if the `&' is immediately followed by an opening brace?) ajr -- If you had eternal life, would you be able to say all the integers?
decot@hpisod2.HP.COM (Dave Decot) (03/11/88)
> decot@hpisod2.HP.COM (Dave Decot) wrote: > >The problem of deciding what their type is solved for now (and possibly > >always) by stating in the standard that such syntax has no inherent type > >and must be cast or assigned to the desired type. > > They're not, but the point is that this is a totally new meaning for a > cast. Usually, a cast is a unary operator. Here, it's part of the > description, like a declaration. No, I intend that as far as the language is concerned, {...} is an expression that has a value, but there are only two operations defined on such values: assigning it to an lvalue using '=', or casting it to the appropriate aggregate type. This concept is somewhat the cousin of (void *), which generates pointers to values that are not usable directly; such pointers must be cast to some other pointer type before the object to which they point can be used. > To be specific: "(int)f" is an > expression that gets an int-ish value for the floating expression f. > It doesn't change f. Depends on what you mean by "f". This cast changes the bit pattern used for representing the value, surely. Pointer casts change the type of the value to which the expression points, which may give them a completely different abstract interpretation. > In your proposal, (struct a){...} and (struct b){...} imply different > values for {...}. What do you mean by "different values"? Of course they are different, they're of different types! If you mean "bit patterns", this is also true of your cast example above. Anyway, this same syntax represents the same type of typeless value that could be said is used for initializers; the value of these depends on the type of the variable which it initializes. > This is very inconsistent, even worse than the inconsistencies > between casting pointers and casting numerical types. It's more similar to casting numerical types than casting pointers, and I think it should be, in order to make these things look like constants. > Also, your (struct ..) cast will produce an lvalue, > which is also a big inconsistency. That is a misinterpretation, and I'm not sure how you arrived at it. Cast only produce rvalues; I assumed this would be obvious. Dave Decot hpda!decot
henry@utzoo.uucp (Henry Spencer) (03/12/88)
> I fail to see that the committee has drawn and observed "need" as > a clear boundary for what should be standardized. They have tried. Sometimes they've let their enthusiasm run away with them; these are reprehensible lapses that should not be considered an excuse to others to do likewise! > > [expletive deleted] Speaking as a user and an implementor, this is an > > abortion if there ever was one. > > Thank you for the feedback. But I wonder if you would be so kind as to > elaborate on this comment... *Why* introduce a new notion of something that doesn't have a type (actually it does have a type, some sort of curious mix of the types of the things inside it) when it is easy to invent a syntax (or borrow the one from the GNU compiler) that specifies the type?!? > > ... probably the GNU compiler's approach, which avoids this > > hideous botch entirely. > > I wonder if you would mind summarizing that approach for those of us who > don't have access to that compiler's source code. As I recall it -- I have not studied the GNU compiler closely yet -- the technique used is a sort of "cast with an initializer". > At any rate, your comment seems to imply that this is existing practice, > so I am having trouble seeing why this is a topic that should not be > standardized. "Existing practice" means that it has been out there for a while, that people other than its implementors have used it at some length, and that it has been used for more than just toy programs. That does not happen overnight, the GNU compiler is very new, and the draft standard is (theoretically) in virtually its final state. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
peter@sugar.UUCP (Peter da Silva) (03/12/88)
In article ... henry@utzoo.uucp (Henry Spencer) writes: > foo = { ... }; > It is agreed that the latter form is more convenient. But we were talking > about *needs*, in the context of an existing language, not about a wishlist > for a new language. I implemented just this construct in a copy of the Small-C compiler I was playing around with about 6 years ago. I had just picked up a copy of the BCPL book and wanted to play with the concepts. I also implemented this: foo = { for(i = 0; i < 10; i++) if(...) break; i; }; in analogy to the BCPL: foo = $( ... resultis i; $) Back to the subject.. the problem of what type an aggregate constant is is a lot easier in Small-C. It's only got 4 types. But if you need prior art to consider this, well here's two examples (half-smiley). > way to do it is probably the GNU compiler's approach, which avoids this > hideous botch entirely. What's the GNU compiler's approach? -- -- Peter da Silva `-_-' ...!hoptoad!academ!uhnix1!sugar!peter -- Disclaimer: These U aren't mere opinions... these are *values*.
karl@haddock.ISC.COM (Karl Heuer) (03/14/88)
In article <8803091705.AA09183@explorer.dgp.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes: >I think it's clear that a new syntax, such as Karl Heuer's, is required. >I would prefer a symbol rather than a keyword, but that's just me. I'd prefer a less verbose syntax, too, but I can't think of anything that isn't arbitrary and doesn't overload an existing syntax. >(But: how about any of backquote, dollar, at (@), or right square bracket? >Perhaps unary comma? Perhaps if the `&' is immediately followed by an >opening brace?) Void the first three; I don't think we should add to the character set for something this simple. Unbalanced brackets would be a big headache (and possibly an ambiguity; I wouldn't want to bet that this construct can never appear inside brackets). With unary comma, or ampersand-brace, where are you going to put the type information? And in the latter case, if you want the aggregate itself rather than a pointer would you have to write `*&{...}`? Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
franka@mmintl.UUCP (Frank Adams) (03/16/88)
>They're not, but the point is that this is a totally new meaning for a >cast. Usually, a cast is a unary operator. Here, it's part of the >description, like a declaration. ... In your proposal, (struct a){...} >and (struct b){...} imply different values for {...}. ... Also, your >(struct ..) cast will produce an lvalue, which is also a big inconsistency. This is the wrong the interpretation of this syntax. If such a syntax is adopted, the correct interpretation runs as follows: An expression of the form {...} is of an anonymous struct type, whose components are unnamed, and have the types of the expressions given. Casting a struct to another struct results in an element by element cast of the components of the first struct to the components of the second. Likewise for casting a struct to an array. Taking the address of a constant results in a literal copy of the constant being allocated, and the result is a constant pointer to that literal. I don't believe that K&R anywhere specify the semantics of casting structs; perhaps X3J11 does. I am sure that there is a fair amount of (non-portable) code out there which assumes that such casts are interpreted as "take as". Just how much, I don't know. The main problem with this proposal is the parsing problem. When do {}'s enclose a struct literal, and when a compound statement? The parser must be able to tell when it sees the first {. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
henry@utzoo.uucp (Henry Spencer) (03/20/88)
>I don't believe that K&R anywhere specify the semantics of casting structs; >perhaps X3J11 does. I am sure that there is a fair amount of (non-portable) >code out there which assumes that such casts are interpreted as "take as". I doubt it, given that most existing compilers refuse to cast structs at all. X3J11 says you can't cast structs (except to void). K&R doesn't mention the issue at all, since it dates back to a time when there were no struct values at all. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
john@viper.Lynx.MN.Org (John Stanley) (03/24/88)
In article <2768@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >>They're not, but the point is that this is a totally new meaning for a >>cast. Usually, a cast is a unary operator. Here, it's part of the >>description, like a declaration. ... In your proposal, (struct a){...} >>and (struct b){...} imply different values for {...}. ... Also, your >>(struct ..) cast will produce an lvalue, which is also a big inconsistency. > >This is the wrong the interpretation of this syntax. If such a syntax is >adopted, the correct interpretation runs as follows: While I agree that the original poster had the wrong idea (it's pretty obvious that a constant, struct or not, can't possibly be an lvalue), I somewhat resent the attitude that your interpretation is "The one and only" correct one. I happen to disagree with part of your interpretation. Does that mean I'm wrong, or just that there's still discussion necessary? > An expression of the form {...} is of an anonymous struct type, > whose components are unnamed, and have the types of the > expressions given. Casting a struct to another struct results > in an element by element cast of the components of the first > struct to the components of the second. Likewise for casting a > struct to an array. I think you're on the right track, and I can see some definate usefulness in the definition as you've defined it, but it looks like we might run into some problems in implementing it. What if the struct(s) have a different number of elements? What happens if you cast a struct containing a long into a character array? This is a start, but it needs more work. > Taking the address of a constant results in a literal copy of > the constant being allocated, and the result is a constant > pointer to that literal. I can't see any usefulness to this part of your proposal. It introduces the necessity for dynamic creation of data with the mechinism compleatly hidden from the programmer. If the programmer wants a copy, let the programmer do it. Let the programmer treat a constant struct as a constant, not something that's going to move every time he/she calls a function containing one. A constant struct should be allocated as part of the constant data page same as any string. Currently, there's no difference between: char aba[10] = "abcdefghi"; and char aba[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\0'}; and I can't see any reason we should change this aspect of the language... >The main problem with this proposal is the parsing problem. When do {}'s >enclose a struct literal, and when a compound statement? The parser >must be able to tell when it sees the first {. The parser doesn't need to know anything. It's not the parsers job to know anything about compound statements or structs... The compiler, on the other hand, should be able to differentiate from context (same way it would when compiling a variable definition line like the char array one given above. >Frank Adams ihnp4!philabs!pwa-b!mmintl!franka >Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108 --- John Stanley (john@viper.UUCP) Software Consultant - DynaSoft Systems UUCP: ...{amdahl,ihnp4,rutgers}!meccts!viper!john
franka@mmintl.UUCP (Frank Adams) (03/29/88)
In article <744@viper.Lynx.MN.Org> john@viper.Lynx.MN.Org (John Stanley) writes: >In article <2768@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: > >[Quoting Henry Spencer, if memory serves. Henry, just to set the record > > straight, was commenting on someone else's proposal, not mine.] > >>They're not, but the point is that this is a totally new meaning for a > >>cast. Usually, a cast is a unary operator. Here, it's part of the > >>description, like a declaration. ... Also, your (struct ..) cast will > >>produce an lvalue, which is also a big inconsistency. > > > >This is the wrong the interpretation of this syntax. If such a syntax is > >adopted, the correct interpretation runs as follows: > > While I agree that the original poster had the wrong idea, I somewhat >resent the attitude that your interpretation is "The one and only" >correct one. The attitude you resent is a figment of your imagination. I was, of course, just expressing my opinion. You are free to agree or disagree. I've even been wrong once or twice in my life (:-). > >Casting a struct to another struct results in an element by element cast > >of the components of the first struct to the components of the second. > >Likewise for casting a struct to an array. > >What if the struct(s) have a different number of elements? To match the K&R initialization syntax as closely as possible, when casting to a struct with more elements, set the excess to zeros. When casting to a struct with fewer elements, one could either ignore the extra ones, or report an error from the compiler. I would lean toward the latter. This does mean that extra braces in initializations become non-optional. That is, one can no longer write: int x[2][2] = {1, 2, 3, 4}; but must instead use int x[2][2] = {{1, 2}, {3, 4}}; This is a non-trivial change. It may be possible to adjust the definition so that this does not happen; I'll have to think about it. >What happens if you cast a struct containing a long into a character array? The long gets converted to a character. C remains an industrial-strength language. > > Taking the address of a constant results in a literal copy of > > the constant being allocated, and the result is a constant > > pointer to that literal. > > I can't see any usefulness to this part of your proposal. It >introduces the necessity for dynamic creation of data with the >mechinism compleatly hidden from the programmer. You misunderstand. I want the *compiler* to allocate the literal copy, not the *program*. The same way it does now for statements like: char * p = "This is a string."; >Currently, there's no difference between: > char aba[10] = "abcdefghi"; > and > char aba[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\0'}; >and I can't see any reason we should change this aspect of the language... Right. Under this proposal, there is also no difference between: char *abc = "abcdefghi"; and char *abc = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\0'}; Whereas the latter is currently illegal. > >The main problem with this proposal is the parsing problem. When do {}'s > >enclose a struct literal, and when a compound statement? The parser > >must be able to tell when it sees the first {. > >It's not the parsers job to know anything about compound statements or >structs... The compiler, on the other hand, should be able to >differentiate from context (same way it would when compiling a variable >definition line like the char array one given above). Guess again. "The part of the compiler which differentiates things from context" is a fairly good definition of the parser. You are perhaps confusing it with the scanner, which divides the source code into tokens. (This terminology is not completely standard, but very nearly so.) Roughly, the problem is that one must look arbitrarily far ahead in the source code to disambiguate the two constructs in some cases. Modern parsing techniques depend on being able to do so relatively quickly. Compare, for example, the following statements: {1, 2, 3, 4, 5, 6, 7;} vs {1, 2, 3, 4, 5, 6, 7}; Now, neither of these statements actually does anything, but both are legal C statements (the first already, the second with the proposed enhancement). The first is a compound statement, containing no declarations and a single enclosed statement. That statement is an expression, involving 7 constants, and 6 "," operators. The second is an expression statement; the expression is anonymous structure constant, with 7 components. Yet, we cannot tell them apart until we get practically to the end. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108