cs211s14@uhccux.uhcc.hawaii.edu (Julian Cowley) (09/29/89)
I have some basic questions regarding arrays and pointers: int a[2][3][5], ***ippp, **ipp, *ip, i, j; i = a[0][0][0]; /* ok */ ip = &a[0][0][0]; /* ok */ ip = a[0][0]; /* why? */ ipp = a[0]; /* why? */ ippp = a; /* why? */ i = ipp[i][j]; /* why^2? */ Why are the latter expressions legal? For instance, I thought that a[0][0] is interpreted as pointer to array 5 of int and ip as a pointer to int, so they would be incompatible. It becomes especially confusing with the next expression: a[0] is a pointer to an array 3 of array 5 of int, not a pointer to pointer to int. Also, ipp[i][j], as indicated in K&R, becomes *(*(ipp + i) + j). How does the compiler know what size to multiply i by? It would seem to me that by the rules of pointer arithmetic, i would be multiplied by the size of a pointer to int and would give incorrect results. Basically what I'm asking here is how the compiler decides that two pointer expressions are of the same type and how it goes about deciding the size of a pointed-to object. Thanks for your help. Julian Cowley cs211s14@uhccux.uhcc.hawaii.edu cs211s14@uhccux.bitnet
flaps@dgp.toronto.edu (Alan J Rosenthal) (09/29/89)
cs211s14@uhccux.uhcc.hawaii.edu (Julian Cowley) writes: >int a[2][3][5], ***ippp, **ipp, *ip, i, j; > >i = a[0][0][0]; /* ok */ >ip = &a[0][0][0]; /* ok */ > >ip = a[0][0]; /* why? */ >ipp = a[0]; /* why? */ >ippp = a; /* why? */ > >i = ipp[i][j]; /* why^2? */ >Why are the latter expressions legal? For instance, I thought >that a[0][0] is interpreted as pointer to array 5 of int and ip >as a pointer to int, so they would be incompatible. Well, the answer is that ipp = a[0] and ippp = a are not legal! What compiler are you using? (rhetorical question) PCC says (sunos 3.5): "test.c", line 9: warning: illegal pointer combination "test.c", line 10: warning: illegal pointer combination However, ip = a[0][0] is fine. a[0][0] is array 5 of int, not pointer to array 5 of int. (I assume the reason you thought it odd that i = ipp[i][j] was legal is because you thought that ipp = a[0] was legal.) ajr
cs211s14@uhccux.uhcc.hawaii.edu (Julian Cowley) (09/29/89)
In article <1989Sep28.205805.9786@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes: >I wrote this: >>int a[2][3][5], ***ippp, **ipp, *ip, i, j; >> >>ip = a[0][0]; /* why? */ >>ipp = a[0]; /* why? */ >>ippp = a; /* why? */ > >Well, the answer is that ipp = a[0] and ippp = a are not legal! What compiler >are you using? (rhetorical question) The Ultrix 3.1 cc compiler, which I thought was derived from PCC (i.e., reliable). Even lint does not complain about the expressions. Well, at least that's cleared up. So much for getting concrete answers to simple questions by running a test program through a compiler. Julian Cowley cs211s14@uhccux.uhcc.hawaii.edu cs211s14@uhccux.bitnet
chris@mimsy.UUCP (Chris Torek) (09/30/89)
Concerning the bogus acceptance of int **ipp; ipp = <expression of type pointer-to-array-5-of-int>; in article <4967@uhccux.uhcc.hawaii.edu> cs211s14@uhccux.uhcc.hawaii.edu (Julian Cowley) writes that he was using >The Ultrix 3.1 cc compiler, which I thought was derived from >PCC (i.e., reliable). The Ultrix VAX `cc' compilers (all of them) are derived from buggy 4.2BSD VAX compilers. One would think that, 4.3BSD-tahoe having been out for several years, including its considerably less buggy VAX PCC, DEC might have at least imported some of the more major fixes. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
karzes@mfci.UUCP (Tom Karzes) (10/03/89)
In article <19880@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: -Concerning the bogus acceptance of - - int **ipp; - ipp = <expression of type pointer-to-array-5-of-int>; - -The Ultrix VAX `cc' compilers (all of them) are derived from buggy -4.2BSD VAX compilers. One would think that, 4.3BSD-tahoe having been -out for several years, including its considerably less buggy VAX PCC, -DEC might have at least imported some of the more major fixes. This isn't entirely accurate. The original C compilers, including the original pcc, all accepted this. Basically, it wouldn't complain about such assignments provided the number of *'s and []'s matched. This clearly doesn't make much sense in any cases involving more than one level of this, but I know that Dennis Ritchie once claimed that it was legal C. Perhaps it was regarded as a sloppy shortcut (I'm not trying to justify it, because I've always hated it). Perhaps he actually regarded it as a bug which had lapsed into a feature. Here's an excerpt from some mail that Bjarne sent me several years ago when we were discussing this issue: >PS Dennis claims that this is C: >main() >{ > int a[5][7] ; > int (*p)[5][7]; > p = (int***) a; /* no & */ > printf("a %d p %d *p %d\n",a,p,*p); /* a == p == *p !!! */ > (*p)[2][4] = 123 ; > printf("%d\n",a[2][4]); /* 123 */ >} >It works! Amazing! My original complaint was that C didn't allow the address-of operator to be applied to arrays. In the case of array "a" above, I calimed that "&a" should be equivalent to "(int (*)[5][7]) a", and in my original example I used this cast in the assignment to "p". Apparently Dennis claimed that you could get away with using "(int ***) a", in spite of the fact that the types are incompatible and could never be used interchangeably. My impression is that this has been "fixed" from time to time in various pcc-derived compilers. I don't know what the latest AT&T and BSD pcc compilers do. My personal preference is to "fix" it and give an error in cases like this. I can imagine 3 cases when this might arise: 1. It was a genuine bug which needed to be fixed. 2. The user knew what he/she wanted, but didn't know to express it in C, and eventually discovered that using this cast made the compiler shut up and accept the assignment. In this case the user simply didn't know C and could very well be misled by the fact that the compiler accepts it, even if it happens to do what was intended. 3. The user knows how to do it the right way, but knows that the compiler will accepts this and is just being lazy. In this case he/she should probably have just used the correct cast in the first place.