boemker@hpfcdc.HP.COM (Tim Boemker) (01/10/88)
What's wrong with this program?
main()
{
int *i;
int j[1];
((int [1]) i) [0] = 1;
}
gwyn@brl-smoke.UUCP (01/12/88)
In article <5080009@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes:
-What's wrong with this program?
-main()
-{
- int *i;
- ((int [1]) i) [0] = 1;
-}
How can you turn a pointer into an array? It makes no sense.
Just use i[0] = 1; which is the same as *i = 1;.
boemker@hpfcdc.HP.COM (Tim Boemker) (01/13/88)
> In article <5080009@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes: > -What's wrong with this program? > -main() > -{ > - int *i; > - ((int [1]) i) [0] = 1; > -} > > How can you turn a pointer into an array? It makes no sense. > Just use i[0] = 1; which is the same as *i = 1;. Consider int A[1]. A is semantically an array, but the expression "A" is a pointer to the base of that array. The only differences between a pointer and array are (1) when the storage is allocated and (2) how index calculations are made. Using i[i] instead of *i may be fine if the array in question is one dimensional, but it doesn't work exactly the same way when the array is multidimensional. Consider int *A. If I know that A points to a 10x20 array, I might like to address elements as A[i][j]. I can do the indexing math myself, as in *(A + i * 20 + j), but that's not what the question is really about. I want to know why a syntactically correct and semantically meaningful expression is not allowed. If you need further provocation, consider this program: main() { int A[1]; ( (int [1]) A ) [0] = 0; } My C compiler doesn't like that construction, either, presumably for the same reason that it didn't like the one in the first example. But please explain to me why it's illegal to cast an expression into it's natural type! Why can't I cast an array as an array?
throopw@xyzzy.UUCP (Wayne A. Throop) (01/13/88)
> boemker@hpfcdc.HP.COM (Tim Boemker) > What's wrong with this program? > main() { > int *i; > int j[1]; > ((int [1]) i) [0] = 1; > } Lint has this to say about it: t17.c ============== (4) illegal lhs of assignment operator (4) warning: i may be used before set (3) warning: j unused in function main (5) warning: main() returns random value to invocation environment In addition to the minor faults, that no exit value was provided, j was unused, and i was used before it was initialized, lint claims that the lhs of the assignment operator is illegal. Which isn't quite right, in that it really should have complained about the cast. But even if we accept the dubious legality of the cast, which is justified only by very broad interpretation of K&R, (how do you convert a pointer-valued expression to an array-valued expression, anyway?), the resulting expression being subscripted would have to be a temporary array (with, for this reason, no aliases), and the whole assignment becomes a monumentally obfuscated no-op. (In particular, it does *NOT* by any remote stretch of the imagination initialize i.) But clearly K&R did not intend to allow anything to be cast to array type, since casts are defined as conversions, and the allowable conversions do not include any that result in arrays. -- I think it's time to stop carping on the blunders of the President and give him some credit for creativity. I mean, where do you even FIND a Jewish hard-line conservative Republican pot-smoker? --- A. Whitney Brown -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
boemker@hpfcdc.UUCP (01/13/88)
> But even if we accept the dubious legality of the cast, which is > justified only by very broad interpretation of K&R, (how do you convert > a pointer-valued expression to an array-valued expression, anyway?), the > resulting expression being subscripted would have to be a temporary > array (with, for this reason, no aliases), and the whole assignment > becomes a monumentally obfuscated no-op. (In particular, it does *NOT* > by any remote stretch of the imagination initialize i.) > But clearly K&R did not intend to allow anything to be cast to array > type, since casts are defined as conversions, and the allowable > conversions do not include any that result in arrays. 1. I'm not so sure about K&R's intentions. True, a cast is a conversion, but the book does not explicitly define the set of legal conversions; it only lists conversions. The list is not necessarily complete. 2. Whenever an array identifier appears in an expression, it is treated as being a pointer to the first element of the array. Casting an expression as an array is just asking that expression to be used as a pointer to the base element of a (mutli-dimensional) rectangular collection of elements. Using an expression of type array is defined, and the object referenced is not the whole collection of elements but a pointer to the collection (pp. 195 bottom and 210 top). Saying that the resulting expression would have to be a temporary array does not make sense under K&R, and it shows a misunderstanding of its concept of arrays: every array expression of the form A[i] is equivalent to the pointer expression *(A+i).
chris@mimsy.UUCP (Chris Torek) (01/14/88)
In article <546@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes: [regarding the cast] >> ((int [1]) i) [0] >But clearly K&R did not intend to allow anything to be cast to array >type, since casts are defined as conversions, and the allowable >conversions do not include any that result in arrays. Or, to put it another way, the result of a cast is an rvalue, and C does not have array rvalues. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
boemker@hpfcdc.UUCP (01/15/88)
> I believe that Standard C does not allow type casting on the left of the > = sign. How about this: int i; char *c; c = (char *) &i; * (int *) c = 0; Are you saying that Standard C doesn't allow c to be recast in that assignment? > I have also discovered that SUN and APOLLO C allow this while most other C > compilers do not???! So the Sun accepts constructions like ((int [1]) i) [0] = 0; ? Does it work?
chris@mimsy.UUCP (Chris Torek) (01/15/88)
In article <5080010@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes: >... Consider int *A. If I know that A points to a 10x20 array, Given that declaration, A cannot point to a 10 x 20 array. It *can* point to the first element of the first row of such an array [see example below], from which all other element addresses can be computed; but it cannot point to the entire array. This is precisely the difference between a pointer to an object and a pointer to an array N of objects: only the latter points to the entire array. >I might like to address elements as A[i][j]. I can >do the indexing math myself, as in *(A + i * 20 + j), but that's not >what the question is really about. I want to know why a syntactically >correct and semantically meaningful expression is not allowed. Because, given the way C is defined, it is not semantically meaningful! One small (?) tweak---allow entire arrays to be rvalues---and it becomes meaningful, but it is not now so. >Why can't I cast an array as an array? Because rvalues cannot be arrays, and the result of a cast is an rvalue. Rvalues *can* be *pointers* to arrays: int *A, i, j; ... /* here we decide (by fiat or by analysis) that A points to the first element of X[10][20], i.e., A == &X[0][0], and then we set X[i][j] through A: */ ((int (*)[20])A)[i][j] = 1; ---although this has the limitation that all but the first dimension must be known at compile time, and again, this is precisely the same limitation as the one that exists for formal array parameters. -------- Note also that the cast replaces the first `array N of' with `pointer to'. This is the general rule that reduces arrays to pointers in C expressions (except as arguments to sizeof). If we decide that A points to the first element of `int Z[10]', and we want to set Z[5], we can write this: ((int (*))A)[5] = 999; but this reduces to ((int *)A)[5] = 999; or just A[5] = 999; so this is really rather boring. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/15/88)
In article <5080010@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes: > int A[1]; > ( (int [1]) A ) [0] = 0; >Why can't I cast an array as an array? The second `A' above is the NAME of an array. In this context it gets converted right away into a pointer to its first element. You cannot legitimately convert a pointer into an array.
throopw@xyzzy.UUCP (Wayne A. Throop) (01/18/88)
> boemker@hpfcdc.HP.COM (Tim Boemker) > I want to know why a syntactically > correct and semantically meaningful expression is not allowed. > If you need further provocation, consider this program: > main() > { > int A[1]; > ( (int [1]) A ) [0] = 0; > } The question is ill formed. The above cast, while it *is* syntactically correct, is *NOT* semantically meaningful. The real question is why were the rules that give C syntax its semantics chosen in such a way as to make that cast meaningless. For a full answer, one would have to ask dmr, but the paraphrase of the question Tim asks can be addressed: > Why can't I cast an array as an array? To review the rules: casts take the value of the target expression and convert this value to a new type. An array, when it appears in an expression, evaluates (yields a value) with pointer type, not array type. Thus, the cast of what appears to be something to its own type is, in fact, an attempt to convert a pointer to an array, not an attempt to cast an array as an array. Now, why were these rules chosen? Well, the rule that really gets in the way here is the rule about how arrays are to be treated when evaluated. This special treatment of arrays in its turn was based on the unification of array subscripting and address arithmetic in C. In other words, it is the indirect consequence of an attempt to make C a simpler and more conceptually unified language. In retrospect, I think better tradeoffs could have been made, but I don't myself pretend to be a genius language designer, so I tend to accept C as it is, with only modest regrets. -- Giving up on assembly language was the apple in our Garden of Eden: Languages whose use squanders machine cycles are sinful. The LISP machine now permits LISP programmers to abandon bra and fig-leaf. --- Alan J. Perlis Moon calls them Fortran Machines and Lisp Machines, but I would prefer to call them fuzzy mammals and pterodactyls myself. --- Richard P. Gabriel -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
tim@amdcad.AMD.COM (Tim Olson) (01/18/88)
In article <5080012@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes: | > I believe that Standard C does not allow type casting on the left of the | > = sign. | | How about this: | | int i; | char *c; | | c = (char *) &i; | | * (int *) c = 0; | | Are you saying that Standard C doesn't allow c to be recast in that assignment? I believe that the previous poster really meant that C doesn't allow *lvalues* to be cast. In your example, 'c' is not an lvalue, but '*c' is. Therefore, you can write * (int *) c = 0; but not (int)(*c) = 0; -- Tim Olson Advanced Micro Devices (tim@amdcad.amd.com)
gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/18/88)
In article <5080011@hpfcdc.HP.COM> boemker@hpfcdc.HP.COM (Tim Boemker) writes: >2. Whenever an array identifier appears in an expression, it is treated as > being a pointer to the first element of the array. I can think of two exceptions to this: when the array name is the operand of sizeof or the operand of &. > Casting an expression > as an array is just asking that expression to be used as a pointer to the > base element of a (mutli-dimensional) rectangular collection of elements. How do you figure that? A cast operator is supposed to accomplish a virtual assignment of the operand into an object of the specified type, an array in this case, and we should all know that C does not support assignment into an array. > Saying that the resulting expression would > have to be a temporary array does not make sense under K&R, ... Excuse me, but saying anything else does not make sense.