digitalmars.D - Array bounds checking causes algorithmic nasties
- Matthew (13/13) Jul 14 2004 ORJRecordA *begin = &m_database.records[0];
- Lars Ivar Igesund (4/12) Jul 14 2004 Well, the last element should be:
- Matthew (3/14) Jul 14 2004 Not correct. Give it another think. :)
- Lars Ivar Igesund (4/25) Jul 14 2004 Maybe I misunderstand something, but you get an ArrayBoundsError if you ...
- Cabal (4/4) Jul 14 2004 Lars, you are correct in your assumption that this will cause an error.
- Matthew (16/40) Jul 14 2004 Yes, that's my point. I may well be wanting to bring too much C++ method...
- Lars Ivar Igesund (5/35) Jul 15 2004 After rereading your message (rethinking wasn't needed) with some flu
- Matthew Wilson (4/38) Jul 15 2004 do
- Arcane Jill (5/7) Jul 14 2004 And even that won't work if m_database.records.length == 0.
- Walter (10/23) Jul 14 2004 all the
- Matthew (4/32) Jul 14 2004 Doesn't work, since it gives me copies of the record structures, and I n...
- Stewart Gordon (12/23) Jul 14 2004 foreach (inout OBJRecordA o; m_database.records)
- Andrew Edwards (18/62) Jul 14 2004 My experience has been that I can always get an address(index) of an
- Matthew (5/65) Jul 14 2004 their
- Walter (4/13) Jul 14 2004 need their
- Ben Hinkle (8/26) Jul 14 2004 I'd just loop over indices since you get the benefit of array bounds
- Matthew (6/32) Jul 14 2004 Yeah, I'm pretty sure I'm on a losing wicket with this one, but it's a s...
- Matthew (6/41) Jul 14 2004 I'm
- Walter (31/31) Jul 14 2004 I don't know what is happening inside the loop, but what it superficiall...
- Sean Kelly (8/14) Jul 14 2004 I've been trying to come up with a situation where the pointer method is
- Matthew (8/39) Jul 14 2004 That all may be true. My main point is that because one has used the "C"...
- Walter (5/7) Jul 14 2004 I understand, but it may be difficult to implement right, since one stil...
- Matthew (4/11) Jul 14 2004 Well, bearing in mind a weakening resolve to argue this point, I'd say t...
- Regan Heath (35/70) Jul 14 2004 It appears using inout on foreach also gives the originals, and thus
- Matthew (7/66) Jul 14 2004 Excellent work! I'll use that one.
- Rex Couture (2/8) Jul 15 2004 Yeah!
ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't have all the horrible pitfalls of C & C++ which mandate that &ar[N] is the only portable (between arrays and UDTs, and between compilers) syntax. But I still think this chews. I'd rather not have the checking.
Jul 14 2004
Matthew wrote:ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above.Well, the last element should be: m_database.records[m_database.records.length - 1]; Lars Ivar Igesund
Jul 14 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd2op0$n6m$1 digitaldaemon.com...Matthew wrote:Not correct. Give it another think. :)ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above.Well, the last element should be: m_database.records[m_database.records.length - 1];
Jul 14 2004
Matthew wrote:"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd2op0$n6m$1 digitaldaemon.com...Maybe I misunderstand something, but you get an ArrayBoundsError if you do arr[arr.length]; Lars Ivar IgesundMatthew wrote:Not correct. Give it another think. :)ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above.Well, the last element should be: m_database.records[m_database.records.length - 1];
Jul 14 2004
Lars, you are correct in your assumption that this will cause an error. You're wrong in your assumption that this is the ideal behaviour when you want to implement STL style iterators... As Matthew said. Think again... :)
Jul 14 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd33il$1c2l$1 digitaldaemon.com...Matthew wrote:Yes, that's my point. I may well be wanting to bring too much C++ methodology over, but it's a well-established idiom in C++ to enumerate an array by taking the address of the first element, and the one-past-the-post element. Your correction to m_database.records[m_database.records.length - 1]; would mean that I'd not include the last element - the one at [m_database.records.length - 1] - in the enumeration. The problem is that an ArrayBoundsError (should that be an exception??) is thrown, even though I'm not using the element, merely its address. This is compounded when the array is empty, since taking the address of the 0th element also causes the Error My proposal/wish is that the use of ArrayBoundsError checking will be elided in the cases where the element's address is taken. I justify it by suggesting that since the coder is taking the address of the elements, they've already gone for a swim in C-world, and are therefore responsible for themselves."Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd2op0$n6m$1 digitaldaemon.com...Maybe I misunderstand something, but you get an ArrayBoundsError if you do arr[arr.length];Matthew wrote:Not correct. Give it another think. :)ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above.Well, the last element should be: m_database.records[m_database.records.length - 1];
Jul 14 2004
Lars Ivar Igesund wrote:Matthew wrote:After rereading your message (rethinking wasn't needed) with some flu cleared from my brain, I understand that my solution was no solution. Sorry for acting stupid :) Lars Ivar Igesund"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd2op0$n6m$1 digitaldaemon.com...Maybe I misunderstand something, but you get an ArrayBoundsError if you do arr[arr.length]; Lars Ivar IgesundMatthew wrote:Not correct. Give it another think. :)ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above.Well, the last element should be: m_database.records[m_database.records.length - 1];
Jul 15 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd5bi7$1pp2$1 digitaldaemon.com...Lars Ivar Igesund wrote:doMatthew wrote:"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cd2op0$n6m$1 digitaldaemon.com...Maybe I misunderstand something, but you get an ArrayBoundsError if youMatthew wrote:Not correct. Give it another think. :)ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above.Well, the last element should be: m_database.records[m_database.records.length - 1];No worries, mate. :-)arr[arr.length]; Lars Ivar IgesundAfter rereading your message (rethinking wasn't needed) with some flu cleared from my brain, I understand that my solution was no solution. Sorry for acting stupid :)
Jul 15 2004
In article <cd2mgr$je4$2 digitaldaemon.com>, Matthew says...The workaround for this is ORJRecordA *begin = &m_database.records[0];And even that won't work if m_database.records.length == 0. Farmer gave us the solution to this one a while back. It is: Arcane Jill
Jul 14 2004
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd2mgr$je4$2 digitaldaemon.com...ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't haveall thehorrible pitfalls of C & C++ which mandate that &ar[N] is the onlyportable(between arrays and UDTs, and between compilers) syntax. But I still thinkthischews. I'd rather not have the checking.An even better workaround: foreach (OBJRecordA o; m_database.records) { ... }
Jul 14 2004
"Walter" <newshound digitalmars.com> wrote in message news:cd2v21$14n3$1 digitaldaemon.com..."Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd2mgr$je4$2 digitaldaemon.com...Doesn't work, since it gives me copies of the record structures, and I need their addresses.ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't haveall thehorrible pitfalls of C & C++ which mandate that &ar[N] is the onlyportable(between arrays and UDTs, and between compilers) syntax. But I still thinkthischews. I'd rather not have the checking.An even better workaround: foreach (OBJRecordA o; m_database.records) { ... }
Jul 14 2004
Matthew wrote:"Walter" <newshound digitalmars.com> wrote in message news:cd2v21$14n3$1 digitaldaemon.com...<snip>foreach (inout OBJRecordA o; m_database.records) { ... } surely? Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.An even better workaround: foreach (OBJRecordA o; m_database.records) { ... }Doesn't work, since it gives me copies of the record structures, and I need their addresses.
Jul 14 2004
Matthew wrote:"Walter" <newshound digitalmars.com> wrote in message news:cd2v21$14n3$1 digitaldaemon.com...My experience has been that I can always get an address(index) of an array by specifying an int counter in the foreach loop. typedef char[] ORJRecordA; struct database { ORJRecordA[] records; } void main () { database m_database; m_database.records ~= cast(ORJRecordA)"Contents Address 0"; m_database.records ~= cast(ORJRecordA)"Contents Address 1"; foreach(int address, ORJRecordA rec; m_database.records) printf("%2d: %.*s"\n,address,cast(char[])rec); } Ciao, Andrew"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd2mgr$je4$2 digitaldaemon.com...Doesn't work, since it gives me copies of the record structures, and I need their addresses.ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't haveall thehorrible pitfalls of C & C++ which mandate that &ar[N] is the onlyportable(between arrays and UDTs, and between compilers) syntax. But I still thinkthischews. I'd rather not have the checking.An even better workaround: foreach (OBJRecordA o; m_database.records) { ... }
Jul 14 2004
"Andrew Edwards" <ridimz_at yahoo.dot.com> wrote in message news:cd31h6$1901$1 digitaldaemon.com...Matthew wrote:their"Walter" <newshound digitalmars.com> wrote in message news:cd2v21$14n3$1 digitaldaemon.com..."Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd2mgr$je4$2 digitaldaemon.com...Doesn't work, since it gives me copies of the record structures, and I needORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't haveall thehorrible pitfalls of C & C++ which mandate that &ar[N] is the onlyportable(between arrays and UDTs, and between compilers) syntax. But I still thinkthischews. I'd rather not have the checking.An even better workaround: foreach (OBJRecordA o; m_database.records) { ... }Mate, you'll have to explain what you're doing here. This looks like a grand hack. A mighty beguiling one, to be sure, but a hack nonetheless.addresses.My experience has been that I can always get an address(index) of an array by specifying an int counter in the foreach loop. typedef char[] ORJRecordA; struct database { ORJRecordA[] records; } void main () { database m_database; m_database.records ~= cast(ORJRecordA)"Contents Address 0"; m_database.records ~= cast(ORJRecordA)"Contents Address 1"; foreach(int address, ORJRecordA rec; m_database.records) printf("%2d: %.*s"\n,address,cast(char[])rec); }
Jul 14 2004
In article <cd37fn$1iv6$1 digitaldaemon.com>, Matthew says..."Andrew Edwards" <ridimz_at yahoo.dot.com> wrote in message news:cd31h6$1901$1 digitaldaemon.com...Simply put, all arrays (including char[]) has both an index and a value at that index location. foreach normally allows access to the value, however you can always access the index by explicitly identifying it. void main() { char[] string = "this is a string"; foreach(int idx, char c; string) { printf("%d: %c\n",idx,c); string[idx] = c + 1; } printf(string); }My experience has been that I can always get an address(index) of an array by specifying an int counter in the foreach loop. typedef char[] ORJRecordA; struct database { ORJRecordA[] records; } void main () { database m_database; m_database.records ~= cast(ORJRecordA)"Contents Address 0"; m_database.records ~= cast(ORJRecordA)"Contents Address 1"; foreach(int address, ORJRecordA rec; m_database.records) printf("%2d: %.*s"\n,address,cast(char[])rec); }Mate, you'll have to explain what you're doing here. This looks like a grand hack. A mighty beguiling one, to be sure, but a hack nonetheless.
Jul 14 2004
"Andrew" <Andrew_member pathlink.com> wrote in message news:cd3f9r$1vjl$1 digitaldaemon.com...In article <cd37fn$1iv6$1 digitaldaemon.com>, Matthew says...Excellent! I never knew that. :)"Andrew Edwards" <ridimz_at yahoo.dot.com> wrote in message news:cd31h6$1901$1 digitaldaemon.com...Simply put, all arrays (including char[]) has both an index and a value at that index location. foreach normally allows access to the value, however you can always access the index by explicitly identifying it. void main() { char[] string = "this is a string"; foreach(int idx, char c; string) { printf("%d: %c\n",idx,c); string[idx] = c + 1; } printf(string); }My experience has been that I can always get an address(index) of an array by specifying an int counter in the foreach loop. typedef char[] ORJRecordA; struct database { ORJRecordA[] records; } void main () { database m_database; m_database.records ~= cast(ORJRecordA)"Contents Address 0"; m_database.records ~= cast(ORJRecordA)"Contents Address 1"; foreach(int address, ORJRecordA rec; m_database.records) printf("%2d: %.*s"\n,address,cast(char[])rec); }Mate, you'll have to explain what you're doing here. This looks like a grand hack. A mighty beguiling one, to be sure, but a hack nonetheless.
Jul 14 2004
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd2v5r$14vm$2 digitaldaemon.com..."Walter" <newshound digitalmars.com> wrote in message news:cd2v21$14n3$1 digitaldaemon.com...need theirAn even better workaround: foreach (OBJRecordA o; m_database.records) { ... }Doesn't work, since it gives me copies of the record structures, and Iaddresses.For what purpose?
Jul 14 2004
"Walter" <newshound digitalmars.com> wrote in message news:cd3v5d$2qim$1 digitaldaemon.com..."Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd2v5r$14vm$2 digitaldaemon.com...So that the Record instance can hold a pointer to the underlying ORJRecordA structure, which lives in a contiguous block headed by the ORJDatabaseA structure. (This is one of the nice things about OpenRJ: there are only two memory (re-)allocations in the creation of the database from the database file. In almost all circumstances this amounts to one block, since only other threads might incur an allocation that would require the second ORJ allocation to not expand the original block.)"Walter" <newshound digitalmars.com> wrote in message news:cd2v21$14n3$1 digitaldaemon.com...need theirAn even better workaround: foreach (OBJRecordA o; m_database.records) { ... }Doesn't work, since it gives me copies of the record structures, and Iaddresses.For what purpose?
Jul 14 2004
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd481m$adi$2 digitaldaemon.com..."Walter" <newshound digitalmars.com> wrote in messageORJRecordASo that the Record instance can hold a pointer to the underlyingDoesn't work, since it gives me copies of the record structures, and Ineed theiraddresses.For what purpose?structure, which lives in a contiguous block headed by the ORJDatabaseA structure. (This is one of the nice things about OpenRJ: there are onlytwomemory (re-)allocations in the creation of the database from the databasefile.In almost all circumstances this amounts to one block, since only otherthreadsmight incur an allocation that would require the second ORJ allocation tonotexpand the original block.)Ok, I see. For that, I think using the index form of the loop will work, and you can take the address of the item within the loop.
Jul 14 2004
Matthew wrote:ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't have all the horrible pitfalls of C & C++ which mandate that &ar[N] is the only portable (between arrays and UDTs, and between compilers) syntax. But I still think this chews. I'd rather not have the checking.I'd just loop over indices since you get the benefit of array bounds checking on a debug build. I assume on a release build the optimizer can turn it into pointer arithmetic if it wants to so the performance should be the same. or, you can just always tell the compiler to not do bounds checking (never build debug) - it all depends on how much you want to use C/C++ idioms in D.
Jul 14 2004
"Ben Hinkle" <bhinkle4 juno.com> wrote in message news:cd3922$1lkm$1 digitaldaemon.com...Matthew wrote:Yeah, I'm pretty sure I'm on a losing wicket with this one, but it's a shame. I'm also looking at supporting pointer-based range algorithms. Given what I've learned with this, I'm even more inclined than I was before to not support them. Now that's a silver lining! :)ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't have all the horrible pitfalls of C & C++ which mandate that &ar[N] is the only portable (between arrays and UDTs, and between compilers) syntax. But I still think this chews. I'd rather not have the checking.I'd just loop over indices since you get the benefit of array bounds checking on a debug build. I assume on a release build the optimizer can turn it into pointer arithmetic if it wants to so the performance should be the same. or, you can just always tell the compiler to not do bounds checking (never build debug) - it all depends on how much you want to use C/C++ idioms in D.
Jul 14 2004
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd3976$1ls2$1 digitaldaemon.com..."Ben Hinkle" <bhinkle4 juno.com> wrote in message news:cd3922$1lkm$1 digitaldaemon.com...I'mMatthew wrote:Yeah, I'm pretty sure I'm on a losing wicket with this one, but it's a shame.ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = &m_database.records[m_database.records.length]; for(; begin != end; ++begin) { . . . The process halts with an ArrayBoundsError on the second line above. The workaround for this is ORJRecordA *begin = &m_database.records[0]; ORJRecordA *end = begin + m_database.records.length; but it's hardly what I'd call a good solution. I suppose D doesn't have all the horrible pitfalls of C & C++ which mandate that &ar[N] is the only portable (between arrays and UDTs, and between compilers) syntax. But I still think this chews. I'd rather not have the checking.I'd just loop over indices since you get the benefit of array bounds checking on a debug build. I assume on a release build the optimizer can turn it into pointer arithmetic if it wants to so the performance should be the same. or, you can just always tell the compiler to not do bounds checking (never build debug) - it all depends on how much you want to use C/C++ idioms in D.also looking at supporting pointer-based range algorithms.for DTL (I meant) Given what I'velearned with this, I'm even more inclined than I was before to not supportthem.Now that's a silver lining! :)
Jul 14 2004
I don't know what is happening inside the loop, but what it superficially looks like here is trying to apply C style pointer arithmetic optimizations to D. With foreach, I'll argue that 1) it isn't necessary and 2) using the index form, the optimizer can transform it to the pointer form automatically. While doing the C pointer form is still possible in D, such as: ORJRecordA* begin = cast(OBJRecordA*)m_database.records; ORJRecordA* end = begin + m_database.records.length; I'd argue that one will be better off using foreach or the index form. One reason is that using the pointer form is NOT necessarilly the most efficient. Another is that the pointer form can impair more aggressive optimizations. Using the higher level construct will enable advanced compilers to do a better job of code generation than if the source usurps that by going directly to pointer arithmetic. [Note: the 'index form' would be: for (size_t i = 0; i < m_database.records; i++) { ... m_database[i] ...; } ] Small D-style nit: In D, declare pointers as: char* p; rather than the C style: char *p; because in D: char* p,q; // p and q are both pointers to char whereas in C: char *p,q; // p is a pointer, q is a char Using whitespace in this way helps illustrate the left-associativity of D's * rather than the right-associativity of C.
Jul 14 2004
In article <cd3voa$2rie$1 digitaldaemon.com>, Walter says...I'd argue that one will be better off using foreach or the index form. One reason is that using the pointer form is NOT necessarilly the most efficient. Another is that the pointer form can impair more aggressive optimizations. Using the higher level construct will enable advanced compilers to do a better job of code generation than if the source usurps that by going directly to pointer arithmetic.I've been trying to come up with a situation where the pointer method is necessary... but I can't. Combined with slicing, foreach can take care of every situation I can think of. But the slicing is important. It's necessary to be able to sequence across a subset of the contents of an associative container. Speaking of which, is there any built-in support for multisets? I haven't tried associating more than one value with a specific key. Sean
Jul 14 2004
"Walter" <newshound digitalmars.com> wrote in message news:cd3voa$2rie$1 digitaldaemon.com...I don't know what is happening inside the loop, but what it superficially looks like here is trying to apply C style pointer arithmetic optimizations to D. With foreach, I'll argue that 1) it isn't necessary and 2) using the index form, the optimizer can transform it to the pointer form automatically. While doing the C pointer form is still possible in D, such as: ORJRecordA* begin = cast(OBJRecordA*)m_database.records; ORJRecordA* end = begin + m_database.records.length; I'd argue that one will be better off using foreach or the index form. One reason is that using the pointer form is NOT necessarilly the most efficient. Another is that the pointer form can impair more aggressive optimizations. Using the higher level construct will enable advanced compilers to do a better job of code generation than if the source usurps that by going directly to pointer arithmetic. [Note: the 'index form' would be: for (size_t i = 0; i < m_database.records; i++) { ... m_database[i] ...; } ]That all may be true. My main point is that because one has used the "C" address of operator, array bounds checking should not apply. But I can change. :)Small D-style nit: In D, declare pointers as: char* p; rather than the C style: char *p; because in D: char* p,q; // p and q are both pointers to char whereas in C: char *p,q; // p is a pointer, q is a char Using whitespace in this way helps illustrate the left-associativity of D's * rather than the right-associativity of C.Excellent point. Thankfully I've not been bitten by this since I never do multiple declarations on the same line. In fact, I didn't even know this. Nonetheless, I'll try and move my splats.
Jul 14 2004
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd481n$adi$3 digitaldaemon.com...My main point is that because one has used the "C" address of operator, array bounds checking should not apply.I understand, but it may be difficult to implement right, since one still would want to disallow things like: p = &array[array.length + 1];
Jul 14 2004
"Walter" <newshound digitalmars.com> wrote in message news:cd4b5i$gjg$1 digitaldaemon.com..."Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message news:cd481n$adi$3 digitaldaemon.com...Well, bearing in mind a weakening resolve to argue this point, I'd say that's up to the programmer. They've taken a trip to C-world. Let them swim with the sharksMy main point is that because one has used the "C" address of operator, array bounds checking should not apply.I understand, but it may be difficult to implement right, since one still would want to disallow things like: p = &array[array.length + 1];
Jul 14 2004
On Wed, 14 Jul 2004 11:59:33 -0700, Walter <newshound digitalmars.com> wrote:I don't know what is happening inside the loop, but what it superficially looks like here is trying to apply C style pointer arithmetic optimizations to D. With foreach, I'll argue that 1) it isn't necessary and 2) using the index form, the optimizer can transform it to the pointer form automatically. While doing the C pointer form is still possible in D, such as: ORJRecordA* begin = cast(OBJRecordA*)m_database.records; ORJRecordA* end = begin + m_database.records.length; I'd argue that one will be better off using foreach or the index form. One reason is that using the pointer form is NOT necessarilly the most efficient. Another is that the pointer form can impair more aggressive optimizations. Using the higher level construct will enable advanced compilers to do a better job of code generation than if the source usurps that by going directly to pointer arithmetic. [Note: the 'index form' would be: for (size_t i = 0; i < m_database.records; i++) { ... m_database[i] ...; } ]It appears using inout on foreach also gives the originals, and thus allows you to take the address of them, is this guaranteed behaviour? The docs say "inout can be used to update the original elements". void main() { char[] test = "regan"; char *begin = cast(char*)test; char *end = begin+test.length; for(; begin != end; ++begin) { printf("%08x\n",begin); } printf("\n"); foreach(inout char c; test) { printf("%08x\n",&c); } printf("\n"); } prints: 0040f080 0040f081 0040f082 0040f083 0040f084 0040f080 0040f081 0040f082 0040f083 0040f084 ReganSmall D-style nit: In D, declare pointers as: char* p; rather than the C style: char *p; because in D: char* p,q; // p and q are both pointers to char whereas in C: char *p,q; // p is a pointer, q is a char Using whitespace in this way helps illustrate the left-associativity of D's * rather than the right-associativity of C.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 14 2004
"Regan Heath" <regan netwin.co.nz> wrote in message news:opsa5ek4sh5a2sq9 digitalmars.com...On Wed, 14 Jul 2004 11:59:33 -0700, Walter <newshound digitalmars.com> wrote:Excellent work! I'll use that one. <abashed> Actually, all this is now moot, since the implementation of Open-RJ has moved on. Ha ha! </abashed>I don't know what is happening inside the loop, but what it superficially looks like here is trying to apply C style pointer arithmetic optimizations to D. With foreach, I'll argue that 1) it isn't necessary and 2) using the index form, the optimizer can transform it to the pointer form automatically. While doing the C pointer form is still possible in D, such as: ORJRecordA* begin = cast(OBJRecordA*)m_database.records; ORJRecordA* end = begin + m_database.records.length; I'd argue that one will be better off using foreach or the index form. One reason is that using the pointer form is NOT necessarilly the most efficient. Another is that the pointer form can impair more aggressive optimizations. Using the higher level construct will enable advanced compilers to do a better job of code generation than if the source usurps that by going directly to pointer arithmetic. [Note: the 'index form' would be: for (size_t i = 0; i < m_database.records; i++) { ... m_database[i] ...; } ]It appears using inout on foreach also gives the originals, and thus allows you to take the address of them, is this guaranteed behaviour? The docs say "inout can be used to update the original elements". void main() { char[] test = "regan"; char *begin = cast(char*)test; char *end = begin+test.length; for(; begin != end; ++begin) { printf("%08x\n",begin); } printf("\n"); foreach(inout char c; test) { printf("%08x\n",&c); } printf("\n"); } prints: 0040f080 0040f081 0040f082 0040f083 0040f084 0040f080 0040f081 0040f082 0040f083 0040f084
Jul 14 2004
In article <cd3voa$2rie$1 digitaldaemon.com>, Walter says...I'd argue that one will be better off using foreach or the index form. One reason is that using the pointer form is NOT necessarilly the most efficient. Another is that the pointer form can impair more aggressive optimizations. Using the higher level construct will enable advanced compilers to do a better job of code generation than if the source usurps that by going directly to pointer arithmetic.Yeah!
Jul 15 2004