|
|
||||
|
||||
|
|
|
|||
|
On 03/10/12 02:09 PM, Joe keane wrote:
> How about this? > > int f(int x) > { > int a[2]; > int *p; > > p =&a[0]; > *p = 2; > ++p; > *p = 3; > /* printf("%d %d\n", a[0], a[1]); */ > } > > That pretty much has to work, right? Why shouldn't it? > So what's the deal with arrays of arrays? Two for $10. -- Ian Collins |
|
|||
|
On Saturday, March 10, 2012 1:09:33 AM UTC, Joe keane wrote:
> How about this? > > int f(int x) > { > int a[2]; > int *p; > > p = &a[0]; > *p = 2; > ++p; > *p = 3; > /* printf("%d %d\n", a[0], a[1]); */ > } > > That pretty much has to work, right? > > So what's the deal with arrays of arrays? what? |
|
|||
|
On Mar 9, 7:09*pm, j...@panix.com (Joe keane) wrote:
> How about this? > > * * int f(int x) > * * { > * * * * int a[2]; > * * * * int *p; > > * * * * p = &a[0]; > * * * * *p = 2; > * * * * ++p; > * * * * *p = 3; > * * * * /* printf("%d %d\n", a[0], a[1]); */ > * * } > > That pretty much has to work, right? No it does not. The function fails to return an int as promised in the declaration. I don't remember whether this is undefined behavior or a constraint violation. > > So what's the deal with arrays of arrays? Since your sample code does not have any arrays of arrays, we have no idea what your question is. Did you perchance mean something like int f(int x) { int a[4][3]; int (*p)[3]; p = &a[0]; (*p)[1] = 2; ++p; (*p)[2] = 3; /* printf("%d %d\n", a[0][1], a[1][2]); */ return 0; } |
|
|||
|
Barry Schwarz wrote:
> > On Mar 9, 7:09 pm, j...@panix.com (Joe keane) wrote: > > How about this? > > > > int f(int x) > > { > > int a[2]; > > int *p; > > > > p = &a[0]; > > *p = 2; > > ++p; > > *p = 3; > > /* printf("%d %d\n", a[0], a[1]); */ > > } > > > > That pretty much has to work, right? > > No it does not. The function fails to return an int as promised in > the declaration. I don't remember whether this is undefined behavior > or a constraint violation. Prior to C99, these words: ISO/IEC 9899: 1990 6.6.6.4 The return statement A function may have any number of return statements, with and without expressions. If a return statement without an expression is executed, and the value of the function call is used by the caller, the behavior is undefined. Reaching the } that terminates a function is equivalent to executing a return statement without an expression. suggest that the use of the above function was defined in C90, as long as the code didn't use the return value. Both C99 and n1570, only have this much to say on this matter: A function may have any number of return statements. > > So what's the deal with arrays of arrays? > > Since your sample code does not have any arrays of arrays, we have no > idea what your question is. Did you perchance mean something like > > int f(int x) > { > int a[4][3]; > int (*p)[3]; > > p = &a[0]; > (*p)[1] = 2; > ++p; > (*p)[2] = 3; > /* printf("%d %d\n", a[0][1], a[1][2]); */ > return 0; > } I think that leaving the printf statement commented out is a little bit funny. -- pete |
|
|||
|
On 03/10/2012 07:22 PM, pete wrote:
> Barry Schwarz wrote: .... > Prior to C99, these words: > > ISO/IEC 9899: 1990 > 6.6.6.4 The return statement > > A function may have any number of return statements, > with and without expressions. > > If a return statement without an expression is executed, > and the value of the function call is used by the caller, > the behavior is undefined. > Reaching the } that terminates a function is > equivalent to executing a return statement without an expression. > > suggest that the use of the above function was defined in C90, > as long as the code didn't use the return value. > > Both C99 and n1570, only have this much to say on this matter: > > A function may have any number of return statements. They didn't change that aspect of C in C99, they only changed the way it was expressed. 6.9.1p12: "If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.". -- James Kuyper |
|
|||
|
James Kuyper wrote:
> > On 03/10/2012 07:22 PM, pete wrote: > > Barry Schwarz wrote: > ... > > Prior to C99, these words: > > > > ISO/IEC 9899: 1990 > > 6.6.6.4 The return statement > > > > A function may have any number of return statements, > > with and without expressions. > > > > If a return statement without an expression is executed, > > and the value of the function call is used by the caller, > > the behavior is undefined. > > Reaching the } that terminates a function is > > equivalent to executing a return statement without an expression. > > > > suggest that the use of the above function was defined in C90, > > as long as the code didn't use the return value. > > > > Both C99 and n1570, only have this much to say on this matter: > > > > A function may have any number of return statements. > > They didn't change that aspect of C in C99, > they only changed the way it was expressed. > 6.9.1p12: "If the } that terminates a function is reached, > and the value > of the function call is used by the caller, > the behavior is undefined.". Thank you. n1570 is the same way. -- pete |
|
|||
|
In article <ea3cda64-a914-4f34-ba2a-59df5fb9fc93@m13g2000yqi.googlegroups.com>,
Barry Schwarz <schwarz45@yahoo.com> wrote: >Since your sample code does not have any arrays of arrays, we have no >idea what your question is. OK int f(int x) { int a[2][2]; int *p; p = &a[0][0]; *p = 1; p += 2; *p = 2; --p; *p = 3; p += 2; *p = 4; /* printf(...); */ return 0; } |
|
|||
|
jgk@panix.com (Joe keane) writes:
> In article <ea3cda64-a914-4f34-ba2a-59df5fb9fc93@m13g2000yqi.googlegroups.com>, > Barry Schwarz <schwarz45@yahoo.com> wrote: >>Since your sample code does not have any arrays of arrays, we have no >>idea what your question is. > > OK > > int f(int x) > { > int a[2][2]; > int *p; > > p = &a[0][0]; > *p = 1; > p += 2; > *p = 2; > --p; > *p = 3; > p += 2; > *p = 4; > /* printf(...); */ > return 0; > } Great, you've posted some more code. Did you want to say something about it? Your subject header is "i think i found". What exactly do you think you've found? I'm sure the point you're making is clear to you, but you're not conveying it well to the rest of us. As for the code you posted, its behavior is undefined. "p" is an "int*" that's initialized to point to element 0 of a 2-element array a[0] (which happens to be an element of a larger array). "p += 2" causes it to point just past the last element of the array a[0], which is ok. But the "*p = 2;" assigns a value past the end of that array, which has undefined behavior. N1570 section J.2 has a (non-normative) list of undefined behaviors, one of which is: An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6). So what was your question? -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
|
|||
|
In article <4F5BF051.303D@mindspring.com>,
pete <pfiland@mindspring.com> wrote: >Prior to C99, these words: [...] >suggest that the use of the above function was defined in C90, >as long as the code didn't use the return value. I slip into C78. |
|
|||
|
In article <lnipiaewcj.fsf@nuthaus.mib.org>,
Keith Thompson <kst-u@mib.org> wrote: > An array subscript is out of range, even if an object is apparently > accessible with the given subscript (as in the lvalue expression > a[1][7] given the declaration int a[4][5]) (6.5.6). I didn't use 'array subscript' at all! It is fine that in a "a[i][j]" syntax people can check both subsctipts rather than the offset. But it's rather oblique about whether you can increment a 'int *' pointer, e.g. from &a[0][4] to &a[1][0]. It would be kind of sad if this didn't work right. It doesn't overtly address the point. |
|
|||
|
jgk@panix.com (Joe keane) writes:
> In article <lnipiaewcj.fsf@nuthaus.mib.org>, > Keith Thompson <kst-u@mib.org> wrote: >> An array subscript is out of range, even if an object is apparently >> accessible with the given subscript (as in the lvalue expression >> a[1][7] given the declaration int a[4][5]) (6.5.6). > > I didn't use 'array subscript' at all! > > It is fine that in a "a[i][j]" syntax people can check both subsctipts > rather than the offset. But it's rather oblique about whether you can > increment a 'int *' pointer, e.g. from &a[0][4] to &a[1][0]. It would > be kind of sad if this didn't work right. It doesn't overtly address > the point. The array subscript operation is defined in terms of pointer arithmetic; E1[E2] is by definition identical to (*((E1)+(E2))). It follows from that that your example's behavior is undefined. In practice, it's likely to "work", but a compiler is free to generate code assuming that the indices do not exceed the declared bounds of the array. -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
|
|||
|
In article <lnk42ocf5l.fsf@nuthaus.mib.org>,
Keith Thompson <kst-u@mib.org> wrote: >The array subscript operation is defined in terms of pointer >arithmetic; E1[E2] is by definition identical to (*((E1)+(E2))). What is 'array subscript'? An array type is contiguous. What does that mean? int f(int t) { int a[3]; int *p; p = a; ++p; *p = 1; } As we expect, this stores in a consistent location. An array of arrays is contiguous. It doesn't say only the last dimension is contiguous, all of them are. So then the whole thing is. And we have 'sizeof' to prove it. int g(int t) { int b[4][5]; int *p; p = *a; p += 4; *p = 4; p += 2; *p = 6; } If it breaks on the second one, then the array is not 'contiguous'. The compiler can't change it to 'int b[4][8];' because that's not 'contiguous' the way the programmer wanted. I'm just using an 'int *' here. It has to work the same as any other 'int *', pointing to the stack, from malloc, or whatever. I don't think it can 'remember' a bunch of extra stuff. >It follows from that that your example's behavior is undefined. unclear |
|
|||
|
On 3/14/2012 7:34 PM, Joe keane wrote:
> In article<lnk42ocf5l.fsf@nuthaus.mib.org>, > Keith Thompson<kst-u@mib.org> wrote: >> The array subscript operation is defined in terms of pointer >> arithmetic; E1[E2] is by definition identical to (*((E1)+(E2))). > > What is 'array subscript'? The subject of Section 6.5.2.1 of a certain International Standard. > An array type is contiguous. What does that mean? The word "contiguous" is given no special meaning by the International Standard mentioned above, so we must assume that the Standard uses the word in accordance with its meaning in English. There is no formal definition of English, nor any authority that can be called "authoritative" (all dictionaries, lexicons, grammars, and the like being merely derivative works), but one studious observer of English offers con-tig-u-ous adj [L /contiguus/, fr /contingere/ to have contact with] 1 : being in actual contact : TOUCHING 2 : ADJOINING 3 : next or near in time or sequence *syn* see ADJACENT For arrays as described in Section 6.2.5 paragraph 20 of the aforementioned aforementioned Standard, I think we can discard meaning (1) and imagine that meanings (2) and/or (3) are intended. > As we expect, this stores in a consistent location. > > An array of arrays is contiguous. It doesn't say only the last > dimension is contiguous, all of them are. So then the whole thing is. > And we have 'sizeof' to prove it. > > int g(int t) > { > int b[4][5]; > int *p; > > p = *a; > p += 4; > *p = 4; > p += 2; > *p = 6; > } > > If it breaks on the second one, then the array is not 'contiguous'. It "breaks" because it doesn't even compile. More often than I'd like, my own incomplete editing of what started as an English sentence turns it into garbage; has something similar happened here? > unclear You betcha. -- Eric Sosman esosman@ieee-dot-org.invalid |
|
|||
|
jgk@panix.com (Joe keane) writes:
> In article <lnk42ocf5l.fsf@nuthaus.mib.org>, > Keith Thompson <kst-u@mib.org> wrote: >>The array subscript operation is defined in terms of pointer >>arithmetic; E1[E2] is by definition identical to (*((E1)+(E2))). > > What is 'array subscript'? > > An array type is contiguous. What does that mean? > > int f(int t) > { > int a[3]; > int *p; > > p = a; > ++p; > *p = 1; > } > > As we expect, this stores in a consistent location. > > An array of arrays is contiguous. It doesn't say only the last > dimension is contiguous, all of them are. So then the whole > thing is. And we have 'sizeof' to prove it. > > int g(int t) > { > int b[4][5]; > int *p; > > p = *b; // [corrected from p = *a;] > p += 4; > *p = 4; > p += 2; > *p = 6; > } > > If it breaks on the second one, then the array is not 'contiguous'. > > The compiler can't change it to 'int b[4][8];' because that's not > 'contiguous' the way the programmer wanted. Yes, the individual elements are contiguous. However, that fact alone is not enough to guarantee that this sort of "cross-subarray-bounds" indexing will work. > I'm just using an 'int *' here. It has to work the same as any > other 'int *', pointing to the stack, from malloc, or whatever. In fact that's not right, according to remarks in the Standard and also, IIRC, some Defect Reports. Sad but true. > I don't think it can 'remember' a bunch of extra stuff. It can, or at least act as though it does in some ways. The low-order bits are somewhat murky, but the high-order bit is ONE. >>It follows from that that your example's behavior is undefined. > > unclear The Standard does make it clear that some cases of indexing outside the bounds of a single subarray transgress into undefined behavior, and it is likely that the code above falls under the cases intended for that. The Standard is _not_ clear about exactly where the boundaries are as to what is defined and what is undefined in such cases, and that has led to a lot of arguments in the newsgroups about which is which. However, for simple cases like the one shown above, I believe the evidence that they are meant to be undefined behavior is pretty convincing. If you care, an assignment (or initialization) like int *p = (int*) &b; is more likely to work as you expect (ie, and be defined behavior) for the "cross-subarray-bounds" indexing like that shown in the example. So that might be a good way to respond to this issue. |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|