pointer arithmetic

D

dotnetchic

I'm having some trouble interpreting some legacy code...here's a single
line of the kind of pointer arithmetic that baffles me. I need help
both interpreting and understanding the reasoning behind it. Can
someone help me?

*(ioStruct.FrntScrPtrn + uj *(*ioStruct.FrntScrPtrn_NumItemsY)+ui) =
tempChar;

can someone re-write this for me in terms I can understand? i.e., my
first attempt was this, but it's incorrect:

ioStruct.FrntScrPtrn[ uj * ioStruct.FrntScrPtrn_NumItemsY[ui] ] =
tempChar;

Also, is there a purpose for this form of pointer arithmetic? Is it
faster?

Many thanks,
sharon
 
C

Carl Daniel [VC++ MVP]

dotnetchic said:
I'm having some trouble interpreting some legacy code...here's a
single line of the kind of pointer arithmetic that baffles me. I
need help both interpreting and understanding the reasoning behind
it. Can someone help me?

*(ioStruct.FrntScrPtrn + uj *(*ioStruct.FrntScrPtrn_NumItemsY)+ui) =
tempChar;

can someone re-write this for me in terms I can understand? i.e., my
first attempt was this, but it's incorrect:

ioStruct.FrntScrPtrn[ uj * ioStruct.FrntScrPtrn_NumItemsY[ui] ] =
tempChar;

Also, is there a purpose for this form of pointer arithmetic? Is it
faster?

This calculated an index into a 2-dimensional array of variable size:

uj is the "x coordinate", ui is the "y coordinate",
ioStruct.FrntScrPtrn_NumItemsY is the width of the array in the "Y"
dimension, and the array is stored in "column major order" (all points with
the same Y coordinate value are contiguous in the array).

The purpose is simple: C and C++ don't have any built-in concept of a
variable-sized array, so there's no way the compiler can know the length of
the rows in the array at compile time (and it's necessary to know the length
of the major axis of a 2-D array to calculate the offset to an element in
the array).

HTH

-cd
 
D

Doug Harrison [MVP]

I'm having some trouble interpreting some legacy code...here's a single
line of the kind of pointer arithmetic that baffles me. I need help
both interpreting and understanding the reasoning behind it. Can
someone help me?

*(ioStruct.FrntScrPtrn + uj *(*ioStruct.FrntScrPtrn_NumItemsY)+ui) =
tempChar;

can someone re-write this for me in terms I can understand? i.e., my
first attempt was this, but it's incorrect:

ioStruct.FrntScrPtrn[ uj * ioStruct.FrntScrPtrn_NumItemsY[ui] ] =
tempChar;

Also, is there a purpose for this form of pointer arithmetic? Is it
faster?

It looks like someone is simulating 2D array access with a pointer into a
1D array. If I knew exactly what ui, uj, and NumItemsY represent, I could
explain it specifically, but the general pattern for turning a[j] into a
pointer expression is this:

T* a1d = (T*) a;
assert(a1d+i*NumCols+j == &a[j]);

If ui is the row number, uj the column number, and NumItemsY the number of
rows, then your expression represents column-major access (as in Fortran)
vs. the normal row-major access of C++.
 
P

Pavel A.

dotnetchic said:
I'm having some trouble interpreting some legacy code...here's a single
line of the kind of pointer arithmetic that baffles me. I need help
both interpreting and understanding the reasoning behind it. Can
someone help me?

*(ioStruct.FrntScrPtrn + uj *(*ioStruct.FrntScrPtrn_NumItemsY)+ui) =
tempChar;

can someone re-write this for me in terms I can understand? i.e., my
first attempt was this, but it's incorrect:

ioStruct.FrntScrPtrn[ uj * ioStruct.FrntScrPtrn_NumItemsY[ui] ] =
tempChar;

ioStruct.FrntScrPtrn[ui+ uj * (*ioStruct.FrntScrPtrn_NumItemsY)] =tempChar;

Also, is there a purpose for this form of pointer arithmetic? Is it
faster?

No, not faster. A decent compiler would create same code.
But a pointer and array are actually different concepts; so it really
depends whether the author sees it as array, or not.

--PA
 
D

dotnetchic

Thanks to you all for the quick responses. I have posted the more
complete snippet this time.

for (uj = 0; uj < * ioStruct.FrntScrPtrn_NumItemsX; uj++)
for (ui = 0; ui < * ioStruct.FrntScrPtrn_NumItemsY; ui++)
{
fread(&tempChar, sizeof(tempChar), 1, fInput);
*(ioStruct.FrntScrPtrn + uj
*(*ioStruct.FrntScrPtrn_NumItemsY)+ui) = tempChar;
}
The purpose is simple: C and C++ don't have any built-in concept of a
variable-sized array, so there's no way the compiler can know the length of
the rows in the array at compile time (and it's necessary to know the length
of the major axis of a 2-D array to calculate the offset to an element in
the array).

I don't *believe* these are variable sized arrays, but I could be
wrong. If so, how would overruns be handled (I'm guessing silently
ignored and trashed data/data pointers)?
 
B

Ben Voigt

dotnetchic said:
Thanks to you all for the quick responses. I have posted the more
complete snippet this time.

for (uj = 0; uj < * ioStruct.FrntScrPtrn_NumItemsX; uj++)
for (ui = 0; ui < * ioStruct.FrntScrPtrn_NumItemsY; ui++)
{
fread(&tempChar, sizeof(tempChar), 1, fInput);
*(ioStruct.FrntScrPtrn + uj
*(*ioStruct.FrntScrPtrn_NumItemsY)+ui) = tempChar;
}

That's about the lamest loop I've ever seen. Obviously written for
employment security. It's equivalent to the slightly faster (calling T the
element type of ioStruct.FrntScrPtrn):

const size_t colcount = *ioStruct.FrntScrPtrn_NumItemsY;
size_t rowsleft = *ioStruct.FrntScrPtrn_NumItemsX;
T* p = ioStruct.FrntScrPtrn;
while (rowsleft-- > 0)
{
size_t colsleft = colcount;
while (colsleft-- > 0)
{
fread(&tempChar, sizeof(tempChar), 1, fInput);
*(p++) = tempChar;
}
}

But that still calls fread a bunch of times, so we'll speed that up with:

when sizeof(T) == sizeof(tempChar),

const size_t colcount = *ioStruct.FrntScrPtrn_NumItemsY;
const size_t rowcount = *ioStruct.FrntScrPtrn_NumItemsX;
fread(ioStruct.FrntScrPtrn, sizeof(*ioStruct.FrntScrPtrn), colcount *
rowcount, fInput);

or, when sizeof(T) != sizeof(tempChar), calling T1 the type of tempChar

const size_t colcount = *ioStruct.FrntScrPtrn_NumItemsY;
const size_t rowcount = *ioStruct.FrntScrPtrn_NumItemsX;
size_t elems = colcount * rowcount;
T1 *tempBuffer = (T1*)alloca(elems * sizeof (T1)); // pick your favorite
allocator
fread(tempBuffer, sizeofT1), elems, fInput);
while (elems-- > 0)
ioStruct.FrntScrPtrn[elems] = tempBuffer[elems]; // compiler should
convert this to a pair of pointers...
// deallocate tempBuffer here if not using alloca or garbage collection
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top