This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Some questions on c99, gcc, and multi-dimensional dynamic arrays


To be honest, generally the best way for allocating an N-dimensional
array would be to do it in one huge hunk:

double *make_matrix(size_t N, size_t *dimSizes, size_t sizeOfElement) {
    size_t total = dimSizes[0];
    for(size_t i = 1; i < N; ++i) {
        total *= dimSizes[i];
    }
    return (double*)malloc(total * sizeOfElement);
}

And then manage your own strides using dimSizes.  So for access in a
3D matrix of size 4x5x6, with 1, 2, 3:
size_t dimSizes[3] = {4, 5, 6};
double *mat = make_matrix(3, dimSizes, sizeof(double));
double element = mat[1*5*6 + 2*6 + 3];

  Brian

On Mon, Dec 7, 2009 at 12:24 AM, Cedric Roux <cedric.roux@acri-st.fr> wrote:
> Thanks for your replies John and Axel.
> Problem is I am still not convinced.
> I thought about it this week-end, and here comes
> my reflexions.
>
> So there is make_matrix().
> I will use it as:
>
> double ***x = make_matrix(3, dim, sizeof(double));
>
> to get a matrix of double with 3 dimensions.
> And:
>
> struct dumb ****y = make_matrix(4, dim2, sizeof(struct dumb));
>
> to get a matrix of "struct dumb" with 4 dimensions.
>
> My real question would more be:
> does an access like "x[1][2][3]" gives me what I expect
> on every platform gcc works on? what about the c99 standard
> on that?
>
> If I understand correctly c99, it says we can go from/to
> a void* and get the same pointing stuff. And, if alignment
> is respected it also works to convert to another type,
> when we cast back we get the same address
> (6.3.2.3.7 in n1336.pdf).
> (Correct me if I'm wrong on this one.)
>
> Now, let's stay with double ***.
>
> In make_matrix we setup the array of pointers with void*
> pointers, not double* and double**, which is what we
> really use later on.
>
> Let's become a bit more concrete. Let's say a pointer
> is on 8 bits, so XXXXXXXX in binary.
>
> What if a void* is stored in memory as XXXXXXXX
> but a double, which would point to an 8 bytes
> number (let's say it's a IEEE 754 double) would
> normally be stored as XXXXX000 (let's suppose
> the hardware wants alignment) so that the
> engineers of this CPU said: "uh, but we waste
> 3 bits, let's store double* as YYYXXXXX, so
> we get 8 times more numbers to point to!"
>
> And they invent ldd reg,add and std add,reg
> to load and store using the "extended address"
> or whatever they would call that.
>
> See the problem? Now a void* is no more like a
> double*. And accessing x[1][2][3] would not
> work since x is double*** but the memory it
> points to has been populated with void*,
> so the "ldd reg,add" will miserably fail
> somewhere in the indirections.
>
> Well, that's how I understand c99. Am I
> correct? In practice, are there cases
> such as the hypothetical one I presented?
> Can I trust my code (even if not c99 correct)
> to work on the hardware I will encounter in
> practice? Are there architectures out there
> where it will fail?
>
> Thanks,
> Cédric.
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]