Accessing via a pointer to 2d array.

T

Thes

Hi all,

I have a 2d float array to which I have declared a pointer thus:

float Matrix[4][3] = {/* snipped initialisation */ };
float (*StoredMatrix)[4][3];


So as to create a copy in a program "registry" of my own devising.

I copy the Marix array as follows:

StoredMatrix = malloc(sizeof Matrix);
if(!StoredMatrix)
{
memcpy((void*)StoredMatrix, (void*)Matrix, sizeof Matrix);
}
else
{ /* take action */ }

My question is whether this is legal, and if so whether it is dangerous?
So far, the copied version dereferences OK using the [] operators - eg
using *StoredMatrix[2][1] etc. I'm not finding K&R helpful on the subject.

Any advice appreciated.
TheS
 
J

Joona I Palaste

Thes said:
I have a 2d float array to which I have declared a pointer thus:
float Matrix[4][3] = {/* snipped initialisation */ };
float (*StoredMatrix)[4][3];

So as to create a copy in a program "registry" of my own devising.
I copy the Marix array as follows:
StoredMatrix = malloc(sizeof Matrix);
if(!StoredMatrix)

Surely you mean if (StoredMatrix), or better yet,
if (StoredMatrix != NULL) here? The way you've written here is asking
for trouble.
{
memcpy((void*)StoredMatrix, (void*)Matrix, sizeof Matrix);
}
else
{ /* take action */ }
My question is whether this is legal, and if so whether it is dangerous?
So far, the copied version dereferences OK using the [] operators - eg
using *StoredMatrix[2][1] etc. I'm not finding K&R helpful on the subject.

Correcting the obvious bug, I don't see any problem. Arrays are
guaranteed to be contiguous, so you'll get no alignment or offset
problems.
 
T

Thes

Joona said:
Thes said:
Hi all,

I have a 2d float array to which I have declared a pointer thus:

float Matrix[4][3] = {/* snipped initialisation */ };
float (*StoredMatrix)[4][3];


So as to create a copy in a program "registry" of my own devising.

I copy the Marix array as follows:

StoredMatrix = malloc(sizeof Matrix);
if(!StoredMatrix)


Surely you mean if (StoredMatrix), or better yet,
if (StoredMatrix != NULL) here? The way you've written here is asking
for trouble.

Oops - yes, that's exactly what I mean. Sorry about that.

{
memcpy((void*)StoredMatrix, (void*)Matrix, sizeof Matrix);
}
else
{ /* take action */ }

My question is whether this is legal, and if so whether it is dangerous?
So far, the copied version dereferences OK using the [] operators - eg
using *StoredMatrix[2][1] etc. I'm not finding K&R helpful on the subject.


Correcting the obvious bug, I don't see any problem. Arrays are
guaranteed to be contiguous, so you'll get no alignment or offset
problems.

Thanks for the reply.

Thes.
 
D

Dan Pop

In said:
I have a 2d float array to which I have declared a pointer thus:

float Matrix[4][3] = {/* snipped initialisation */ };
float (*StoredMatrix)[4][3];

So as to create a copy in a program "registry" of my own devising.

I copy the Marix array as follows:

StoredMatrix = malloc(sizeof Matrix);
if(!StoredMatrix)
{
memcpy((void*)StoredMatrix, (void*)Matrix, sizeof Matrix);
}

This is better written like this:

StoredMatrix = malloc(sizeof *StoredMatrix);
if (StoredMatrix != NULL)
{
memcpy(StoredMatrix, Matrix, sizeof Matrix);
}

Using an explicit test against NULL makes it less likely that you get it
wrong and the casts in the memcpy call are cluttering the code without
buying you anything.
else
{ /* take action */ }

My question is whether this is legal, and if so whether it is dangerous?
So far, the copied version dereferences OK using the [] operators - eg
using *StoredMatrix[2][1] etc. I'm not finding K&R helpful on the subject.

No problems with your code (except for the obvious bug in the if
statement), but it can be improved, so that you can use the
StoredMatrix[2][1] syntax instead of the less natural *StoredMatrix[2][1].

float (*StoredMatrix)[3];
StoredMatrix = malloc(4 * sizeof *StoredMatrix);

Another advantage of this technique is that you can dynamically allocate
"bidimensional" arrays without knowing the number of lines at compile time
only the number of columns must be known.

Dan
 
S

Sheldon Simms

I copy the Marix array as follows: [snip]
memcpy((void*)StoredMatrix, (void*)Matrix, sizeof Matrix);

The casts to void are unnecessary if you have #included string.h, which
you should do.
 
C

CBFalconer

Dan said:
.... snip ...

This is better written like this:

StoredMatrix = malloc(sizeof *StoredMatrix);
if (StoredMatrix != NULL)
{
memcpy(StoredMatrix, Matrix, sizeof Matrix);
}
.... snip ...

No problems with your code (except for the obvious bug in the if

Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location? Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.
 
T

Thes

CBFalconer said:
Dan Pop wrote:

... snip ...


... snip ...



Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location? Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.

Further to that: doing some more testing it seems that when using memcpy
to copy the entire array over to the memory pointed to by the pointer,
there was some problems using [] on the dereferenced pointer. That is,
*StoredMatrix[j] didn't always equal Matrix[j].

If I copied the matrix using a nested loop in i and j strictly setting
*StoredMatrix[j] = Matrix[j] then, obviously, all was well.

This behaviour was observed using MSVC++6 but not gcc on Linux - so I
expect I'm doing something undefined somewhere...

Anyway, thanks for the replies. Bad coding habits being curbed!
Thes
 
D

Dan Pop

In said:
Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location?

The C standard, of course.
Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.

Wrong. Note that the padding bits are part of the object representation.

4 Values stored in non-bit-field objects of any other object type
consist of n × CHAR_BIT bits, where n is the size of an object
of that type, in bytes. The value may be copied into an object
of type unsigned char [n] (e.g., by memcpy); the resulting
^^^^^^^^^^^^^^^
set of bytes is called the object representation of the value.
Values stored in bit-fields consist of m bits, where m is the
size specified for the bit-field. The object representation is
the set of m bits the bit-field comprises in the addressable
storage unit holding it. Two values (other than NaNs) with
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the same object representation compare equal, but values that
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
compare equal may have different object representations.

It doesn't hurt to actually consult the standard when elaborating fancy
scenarios...

Dan
 
D

Dan Pop

In said:
CBFalconer said:
Dan Pop wrote:

... snip ...


... snip ...



Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location? Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.

Further to that: doing some more testing it seems that when using memcpy
to copy the entire array over to the memory pointed to by the pointer,
there was some problems using [] on the dereferenced pointer. That is,
*StoredMatrix[j] didn't always equal Matrix[j].


The bug was elsewhere in your code. The value of *any* object, no matter
how large and complex, can be safely copied with memcpy.

Dan
 
T

Thes

Dan said:
CBFalconer said:
Dan Pop wrote:

... snip ...


This is better written like this:

StoredMatrix = malloc(sizeof *StoredMatrix);
if (StoredMatrix != NULL)
{
memcpy(StoredMatrix, Matrix, sizeof Matrix);
}


... snip ...


No problems with your code (except for the obvious bug in the if


Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location? Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.

Further to that: doing some more testing it seems that when using memcpy
to copy the entire array over to the memory pointed to by the pointer,
there was some problems using [] on the dereferenced pointer. That is,
*StoredMatrix[j] didn't always equal Matrix[j].



The bug was elsewhere in your code. The value of *any* object, no matter
how large and complex, can be safely copied with memcpy.

Dan


Indeed. I've discovered that there is a difference between
*StoredMatrix[j] and (*StoredMatrix)[j] which suprised me.

What are the rules in these cases?

Thes
 
J

Joona I Palaste

Thes said:
Dan said:
In said:
CBFalconer wrote:
Dan Pop wrote:
This is better written like this:

StoredMatrix = malloc(sizeof *StoredMatrix);
if (StoredMatrix != NULL)
{
memcpy(StoredMatrix, Matrix, sizeof Matrix);
}

No problems with your code (except for the obvious bug in the if

Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location? Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.

Further to that: doing some more testing it seems that when using memcpy
to copy the entire array over to the memory pointed to by the pointer,
there was some problems using [] on the dereferenced pointer. That is,
*StoredMatrix[j] didn't always equal Matrix[j].


The bug was elsewhere in your code. The value of *any* object, no matter
how large and complex, can be safely copied with memcpy.

Indeed. I've discovered that there is a difference between
*StoredMatrix[j] and (*StoredMatrix)[j] which suprised me.

What are the rules in these cases?

I'm not altogether sure here, but I think that the first means what
element [j] of StoredMatrix points at, and the second means element
[j] of what StoredMatrix points at.
 
D

Dan Pop

In said:
Dan said:
The bug was elsewhere in your code. The value of *any* object, no matter
how large and complex, can be safely copied with memcpy.
Indeed. I've discovered that there is a difference between
*StoredMatrix[j] and (*StoredMatrix)[j] which suprised me.

What are the rules in these cases?


The [] operator having higher precedence, *StoredMatrix[j] is the same
as *(StoredMatrix[j]), which is NOT what you want in order to access
the element on row i, column j. StoredMatrix is already sending you
beyond the array pointed to by StoredMatrix, if i is not 0.

To preserve your sanity, restrict yourself to pointers to "unidimensional"
arrays, as I've shown in my first post in this thread.

Dan
 
C

CBFalconer

Dan said:
.... snip ...
Recalling that Matrix was defined as an array of floats, each of
which may have padding bits and trap values, what guarantees that
those padding bits and trapvalues are independent of the actual
storage location?

The C standard, of course.
Thus I suspect that the construct is not
strictly legal, but that the chance of actual problems is
miniscule.

Wrong. Note that the padding bits are part of the object representation.

4 Values stored in non-bit-field objects of any other object type
consist of n × CHAR_BIT bits, where n is the size of an object
of that type, in bytes. The value may be copied into an object
of type unsigned char [n] (e.g., by memcpy); the resulting
^^^^^^^^^^^^^^^
set of bytes is called the object representation of the value.
Values stored in bit-fields consist of m bits, where m is the
size specified for the bit-field. The object representation is
the set of m bits the bit-field comprises in the addressable
storage unit holding it. Two values (other than NaNs) with
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the same object representation compare equal, but values that
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
compare equal may have different object representations.

It doesn't hurt to actually consult the standard when elaborating
fancy scenarios...

Why go through an O(N**N) search when we have you to perform those
correlations :)
 
D

Dan Pop

In said:
Why go through an O(N**N) search when we have you to perform those
correlations :)

Maybe because it prevents the brain cells from getting rusty? ;-)

Dan
 

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

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,218
Latest member
JolieDenha

Latest Threads

Top