www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Array bounds checking causes algorithmic nasties

reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
   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
next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
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
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message
news:cd2op0$n6m$1 digitaldaemon.com...
 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];

Not correct. Give it another think. :)
Jul 14 2004
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Matthew wrote:

 "Lars Ivar Igesund" <larsivar igesund.net> wrote in message
 news:cd2op0$n6m$1 digitaldaemon.com...
 
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];

Not correct. Give it another think. :)

Maybe I misunderstand something, but you get an ArrayBoundsError if you do arr[arr.length]; Lars Ivar Igesund
Jul 14 2004
next sibling parent Cabal <cabal myrealbox.com> writes:
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
prev sibling next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message
news:cd33il$1c2l$1 digitaldaemon.com...
 Matthew wrote:

 "Lars Ivar Igesund" <larsivar igesund.net> wrote in message
 news:cd2op0$n6m$1 digitaldaemon.com...

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];

Not correct. Give it another think. :)

Maybe I misunderstand something, but you get an ArrayBoundsError if you do arr[arr.length];

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.
Jul 14 2004
prev sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Lars Ivar Igesund wrote:
 Matthew wrote:
 
 "Lars Ivar Igesund" <larsivar igesund.net> wrote in message
 news:cd2op0$n6m$1 digitaldaemon.com...

 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];

Not correct. Give it another think. :)

Maybe I misunderstand something, but you get an ArrayBoundsError if you do arr[arr.length]; Lars Ivar Igesund

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
Jul 15 2004
parent "Matthew Wilson" <admin.hat stlsoft.dot.org> writes:
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message
news:cd5bi7$1pp2$1 digitaldaemon.com...
 Lars Ivar Igesund wrote:
 Matthew wrote:

 "Lars Ivar Igesund" <larsivar igesund.net> wrote in message
 news:cd2op0$n6m$1 digitaldaemon.com...

 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];

Not correct. Give it another think. :)

Maybe I misunderstand something, but you get an ArrayBoundsError if you


 arr[arr.length];

 Lars Ivar Igesund

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 :)

No worries, mate. :-)
Jul 15 2004
prev sibling next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
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: # ORJRecordA *begin = cast (ORJRecordA *) m_database.records; Arcane Jill
Jul 14 2004
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"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 have

 horrible pitfalls of C & C++ which mandate that &ar[N] is the only

 (between arrays and UDTs, and between compilers) syntax. But I still think

 chews. I'd rather not have the checking.

An even better workaround: foreach (OBJRecordA o; m_database.records) { ... }
Jul 14 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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...
    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

 horrible pitfalls of C & C++ which mandate that &ar[N] is the only

 (between arrays and UDTs, and between compilers) syntax. But I still think

 chews. I'd rather not have the checking.

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
next sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Matthew wrote:

 "Walter" <newshound digitalmars.com> wrote in message
 news:cd2v21$14n3$1 digitaldaemon.com...

 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.

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.
Jul 14 2004
prev sibling next sibling parent reply Andrew Edwards <ridimz_at yahoo.dot.com> writes:
Matthew wrote:
 "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...

   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.

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.

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
Jul 14 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Andrew Edwards" <ridimz_at yahoo.dot.com> wrote in message
news:cd31h6$1901$1 digitaldaemon.com...
 Matthew wrote:
 "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...

   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.

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


 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); }

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
parent reply Andrew <Andrew_member pathlink.com> writes:
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...
 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.

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); }
Jul 14 2004
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Andrew" <Andrew_member pathlink.com> wrote in message
news:cd3f9r$1vjl$1 digitaldaemon.com...
 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...
 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.

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); }

Excellent! I never knew that. :)
Jul 14 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"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...
 An even better workaround:
     foreach (OBJRecordA o; m_database.records)
     {
         ...
     }

Doesn't work, since it gives me copies of the record structures, and I

 addresses.

For what purpose?
Jul 14 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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...
 "Walter" <newshound digitalmars.com> wrote in message
 news:cd2v21$14n3$1 digitaldaemon.com...
 An even better workaround:
     foreach (OBJRecordA o; m_database.records)
     {
         ...
     }

Doesn't work, since it gives me copies of the record structures, and I

 addresses.

For what purpose?

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.)
Jul 14 2004
parent "Walter" <newshound digitalmars.com> writes:
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
news:cd481m$adi$2 digitaldaemon.com...
 "Walter" <newshound digitalmars.com> wrote in message
 Doesn't work, since it gives me copies of the record structures, and I

 addresses.

For what purpose?

So that the Record instance can hold a pointer to the underlying

 structure, which lives in a contiguous block headed by the ORJDatabaseA
 structure. (This is one of the nice things about OpenRJ: there are only

 memory (re-)allocations in the creation of the database from the database

 In almost all circumstances this amounts to one block, since only other

 might incur an allocation that would require the second ORJ allocation to

 expand 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
prev sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
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
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Ben Hinkle" <bhinkle4 juno.com> wrote in message
news:cd3922$1lkm$1 digitaldaemon.com...
 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.

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! :)
Jul 14 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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...
 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.

Yeah, I'm pretty sure I'm on a losing wicket with this one, but it's a shame.

 also looking at supporting pointer-based range algorithms.

for DTL (I meant) Given what I've
 learned with this, I'm even more inclined than I was before to not support

 Now that's a silver lining! :)

Jul 14 2004
parent reply "Walter" <newshound digitalmars.com> writes:
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
next sibling parent Sean Kelly <sean f4.ca> writes:
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
prev sibling next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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
parent reply "Walter" <newshound digitalmars.com> writes:
"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
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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...
 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];

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 sharks
Jul 14 2004
prev sibling next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
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 Regan
 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.

-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 14 2004
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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:
 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

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>
Jul 14 2004
prev sibling parent Rex Couture <Rex_member pathlink.com> writes:
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