variable length array

Discussion in 'C Programming' started by Jean-Claude Arbaut, Jun 3, 2009.

  1. Hi,

    I can use:

    double get(int n, int p, double t[n][p], int i, int j) {
    return t[j];
    }

    and in another function
    double (*u)[];
    t = (double (*)[])calloc(n*p, sizeof(double));
    a=get(n,p,u,i,j);

    Now, how would I declare u for 3 dimensions or more ?
    Jean-Claude Arbaut, Jun 3, 2009
    #1
    1. Advertising

  2. On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    <> wrote:

    >Hi,
    >
    >I can use:
    >
    >double get(int n, int p, double t[n][p], int i, int j) {
    > return t[j];
    >}
    >
    >and in another function
    >double (*u)[];


    I believe this would need to be
    double (*u)[p];
    as in examples 3 and 4 in 6.7.5.2(9)-(10)

    >t = (double (*)[])calloc(n*p, sizeof(double));


    Surely you meant u here, not t. The cast is unnecessary. Furthermore,
    all bits zero need not be the representation of 0.0. A frequently
    recommended construct is
    t = calloc(n, sizeof *t);
    or the malloc "almost equivalent"
    t malloc (n * sizeof *t);

    >a=get(n,p,u,i,j);
    >
    >Now, how would I declare u for 3 dimensions or more ?


    When declaring arrays in functions and pointers to arrays, only the
    high-order dimension can be unspecified/omitted.

    If t3 is going to be defined in the function as
    double t3[x][y][z]
    then u3 will need to be defined as
    double (*u3)[y][z];

    --
    Remove del for email
    Barry Schwarz, Jun 3, 2009
    #2
    1. Advertising

  3. Barry Schwarz wrote:

    > On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    > <> wrote:
    >
    >> Hi,
    >>
    >> I can use:
    >>
    >> double get(int n, int p, double t[n][p], int i, int j) {
    >> return t[j];
    >> }
    >>
    >> and in another function
    >> double (*u)[];

    >
    > I believe this would need to be
    > double (*u)[p];
    > as in examples 3 and 4 in 6.7.5.2(9)-(10)


    There is one in n1256.pdf, p41 :)
    And I'm not a C standard expert, but I tought
    it's legal to have one incomplete dimension.

    gcc -Wall -std=c99 -pedantic doesn't bark at me.
    I know that doesn't prove much, but that's strange.



    >> t = (double (*)[])calloc(n*p, sizeof(double));

    >
    > Surely you meant u here, not t.


    yes

    > The cast is unnecessary.


    Someone just told me that on fr.clc ;-) Actually it's
    a bad habit I got from using a bad compiler that gave
    a warning for uncasted (mc)alloc. I can't remember
    which compiler it was.

    > Furthermore,
    > all bits zero need not be the representation of 0.0. A frequently
    > recommended construct is
    > t = calloc(n, sizeof *t);
    > or the malloc "almost equivalent"
    > t malloc (n * sizeof *t);


    Does it guarantee that memory is zeroed ?

    >> a=get(n,p,u,i,j);
    >>
    >> Now, how would I declare u for 3 dimensions or more ?

    >
    > When declaring arrays in functions and pointers to arrays, only the
    > high-order dimension can be unspecified/omitted.


    Same remark as above.


    > If t3 is going to be defined in the function as
    > double t3[x][y][z]
    > then u3 will need to be defined as
    > double (*u3)[y][z];



    Is there really no way to allocate it ?
    I mean, it's possible with a warning to do

    double *p = malloc(100*sizeof(double));
    a = get(10,10,p,0,0);

    But what should I do to declare it correctly ?
    Jean-Claude Arbaut, Jun 3, 2009
    #3
  4. Jean-Claude Arbaut <> writes:
    > Barry Schwarz wrote:
    >> On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    >> <> wrote:

    [...]
    >>> t = (double (*)[])calloc(n*p, sizeof(double));

    >>
    >> Surely you meant u here, not t.

    >
    > yes
    >
    >> The cast is unnecessary.

    >
    > Someone just told me that on fr.clc ;-) Actually it's
    > a bad habit I got from using a bad compiler that gave
    > a warning for uncasted (mc)alloc. I can't remember
    > which compiler it was.


    Could it have been a C++ compiler?

    >> Furthermore,
    >> all bits zero need not be the representation of 0.0. A frequently
    >> recommended construct is
    >> t = calloc(n, sizeof *t);
    >> or the malloc "almost equivalent"
    >> t malloc (n * sizeof *t);

    >
    > Does it guarantee that memory is zeroed ?


    No, malloc doesn't initialize the allocated space, whereas calloc sets
    it to all-bits-zero. But setting it to all-bits-zero doesn't
    guarantee that all elements will be set to 0.0, since there's no
    guarantee that all-bits-zero is a representation of all-bits-zero.

    You can probably get away with it on most (maybe all?) existing
    systems, but it's not portable. For guaranteed portability, you need
    to set the elements to 0.0 using a loop -- and if you're going to do
    that anyway you might as well just use malloc rather than calloc.
    And, depending on what you're doing with the data, you might not need
    to set *all* the elements to 0.0.

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 3, 2009
    #4
  5. Jean-Claude Arbaut

    Flash Gordon Guest

    Keith Thompson wrote:
    > Jean-Claude Arbaut <> writes:
    >> Barry Schwarz wrote:
    >>> On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    >>> <> wrote:

    > [...]
    >>>> t = (double (*)[])calloc(n*p, sizeof(double));
    >>> Surely you meant u here, not t.

    >> yes
    >>
    >>> The cast is unnecessary.

    >> Someone just told me that on fr.clc ;-) Actually it's
    >> a bad habit I got from using a bad compiler that gave
    >> a warning for uncasted (mc)alloc. I can't remember
    >> which compiler it was.

    >
    > Could it have been a C++ compiler?
    >
    >>> Furthermore,
    >>> all bits zero need not be the representation of 0.0. A frequently
    >>> recommended construct is
    >>> t = calloc(n, sizeof *t);
    >>> or the malloc "almost equivalent"
    >>> t malloc (n * sizeof *t);

    >> Does it guarantee that memory is zeroed ?

    >
    > No, malloc doesn't initialize the allocated space, whereas calloc sets
    > it to all-bits-zero. But setting it to all-bits-zero doesn't
    > guarantee that all elements will be set to 0.0, since there's no
    > guarantee that all-bits-zero is a representation of all-bits-zero.


    I know you meant "since there's no guarantee that all-bits-zero
    represents a floating point 0.0 (or a null pointer)".

    > You can probably get away with it on most (maybe all?) existing
    > systems, but it's not portable. For guaranteed portability, you need
    > to set the elements to 0.0 using a loop -- and if you're going to do
    > that anyway you might as well just use malloc rather than calloc.
    > And, depending on what you're doing with the data, you might not need
    > to set *all* the elements to 0.0.


    If the OP does choose to use calloc, make sure the non-portable
    assumption is documented just in case someone ports the SW later to an
    unusual system where it is a problem.
    --
    Flash Gordon
    Flash Gordon, Jun 3, 2009
    #5
  6. Jean-Claude Arbaut

    luserXtrog Guest

    On Jun 3, 1:03 pm, Flash Gordon <> wrote:
    > Keith Thompson wrote:
    > > Jean-Claude Arbaut <> writes:
    > >> Barry Schwarz wrote:
    > >>> On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    > >>> <> wrote:

    > > [...]
    > >>>> t = (double (*)[])calloc(n*p, sizeof(double));
    > >>> Surely you meant u here, not t.
    > >> yes

    >
    > >>> The cast is unnecessary.
    > >> Someone just told me that on fr.clc ;-) Actually it's
    > >> a bad habit I got from using a bad compiler that gave
    > >> a warning for uncasted (mc)alloc. I can't remember
    > >> which compiler it was.

    >
    > > Could it have been a C++ compiler?

    >
    > >>> Furthermore,
    > >>> all bits zero need not be the representation of 0.0.  A frequently
    > >>> recommended construct is
    > >>>    t = calloc(n, sizeof *t);
    > >>> or the malloc "almost equivalent"
    > >>>    t  malloc (n * sizeof *t);
    > >> Does it guarantee that memory is zeroed ?

    >
    > > No, malloc doesn't initialize the allocated space, whereas calloc sets
    > > it to all-bits-zero.  But setting it to all-bits-zero doesn't
    > > guarantee that all elements will be set to 0.0, since there's no
    > > guarantee that all-bits-zero is a representation of all-bits-zero.

    >
    > I know you meant "since there's no guarantee that all-bits-zero
    > represents a floating point 0.0 (or a null pointer)".
    >
    > > You can probably get away with it on most (maybe all?) existing
    > > systems, but it's not portable.  For guaranteed portability, you need
    > > to set the elements to 0.0 using a loop -- and if you're going to do
    > > that anyway you might as well just use malloc rather than calloc.
    > > And, depending on what you're doing with the data, you might not need
    > > to set *all* the elements to 0.0.

    >
    > If the OP does choose to use calloc, make sure the non-portable
    > assumption is documented just in case someone ports the SW later to an
    > unusual system where it is a problem.


    Sounds like a good spot for an assertion;

    assert(u[0][0]==0.0);

    --
    lxt
    luserXtrog, Jun 3, 2009
    #6
  7. Jean-Claude Arbaut

    James Kuyper Guest

    luserXtrog wrote:
    > On Jun 3, 1:03 pm, Flash Gordon <> wrote:
    >> Keith Thompson wrote:

    ....
    >>> it to all-bits-zero. But setting it to all-bits-zero doesn't
    >>> guarantee that all elements will be set to 0.0, since there's no
    >>> guarantee that all-bits-zero is a representation of all-bits-zero.

    >> I know you meant "since there's no guarantee that all-bits-zero
    >> represents a floating point 0.0 (or a null pointer)".

    ....
    > Sounds like a good spot for an assertion;
    >
    > assert(u[0][0]==0.0);


    Perhaps - but keep in mind that if all-bits-zero is a trap
    representation for 'double', the left operand of the comparison
    expression has undefined behavior, which means (among other less
    annoying possibilities), that your assert might fail to trigger. That
    pretty much eliminates it's usefulness.

    For similar purposes I've used a memcmp() between a zero-initialized
    object and an object of the same size memset() to all-bits-0. That
    completely avoids the undefined behavior mentioned above. Unfortunately,
    it doesn't cover the possibility that all-bits-zero represents a value
    equivalent to a zero-initialized variable, but with a different
    representation. I was willing to live with that possibility; it would
    only have made my program slightly inefficient - it wouldn't have broken it.
    James Kuyper, Jun 3, 2009
    #7
  8. On Wed, 03 Jun 2009 10:36:43 +0200, Jean-Claude Arbaut
    <> wrote:

    >Barry Schwarz wrote:
    >
    >> On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    >> <> wrote:
    >>
    >>> Hi,
    >>>
    >>> I can use:
    >>>
    >>> double get(int n, int p, double t[n][p], int i, int j) {
    >>> return t[j];
    >>> }
    >>>
    >>> and in another function
    >>> double (*u)[];

    >>
    >> I believe this would need to be
    >> double (*u)[p];
    >> as in examples 3 and 4 in 6.7.5.2(9)-(10)

    >
    >There is one in n1256.pdf, p41 :)
    >And I'm not a C standard expert, but I tought
    >it's legal to have one incomplete dimension.


    The example on page 41 shows a pair of declarations, each of which is
    partially incomplete. But as set, none of the incomplete parts remain
    incomplete.

    >
    >gcc -Wall -std=c99 -pedantic doesn't bark at me.
    >I know that doesn't prove much, but that's strange.
    >
    >
    >
    >>> t = (double (*)[])calloc(n*p, sizeof(double));

    >>
    >> Surely you meant u here, not t.

    >
    >yes
    >
    >> The cast is unnecessary.

    >
    >Someone just told me that on fr.clc ;-) Actually it's
    >a bad habit I got from using a bad compiler that gave
    >a warning for uncasted (mc)alloc. I can't remember
    >which compiler it was.
    >
    >> Furthermore,
    >> all bits zero need not be the representation of 0.0. A frequently
    >> recommended construct is
    >> t = calloc(n, sizeof *t);
    >> or the malloc "almost equivalent"
    >> t malloc (n * sizeof *t);


    That should have been
    t = malloc(n*sizeof *t)

    >
    >Does it guarantee that memory is zeroed ?
    >
    >>> a=get(n,p,u,i,j);
    >>>
    >>> Now, how would I declare u for 3 dimensions or more ?

    >>
    >> When declaring arrays in functions and pointers to arrays, only the
    >> high-order dimension can be unspecified/omitted.

    >
    >Same remark as above.
    >
    >
    >> If t3 is going to be defined in the function as
    >> double t3[x][y][z]
    >> then u3 will need to be defined as
    >> double (*u3)[y][z];

    >
    >
    >Is there really no way to allocate it ?
    >I mean, it's possible with a warning to do
    >
    >double *p = malloc(100*sizeof(double));
    >a = get(10,10,p,0,0);


    This is not correct. Even if the compiler calls the diagnostic a
    warning you still invoke undefined behavior. The function is
    expecting a double(*)[p] and you are passing a double*. There is no
    guarantee that the two pointers have the same representation or
    alignment. Also there are several discussions in the archive if it is
    legal to step through a 2D array as if it were a long 1D array.

    >
    >But what should I do to declare it correctly ?


    I showed the definition of the array and the pointer above. You
    assign allocated memory to the pointer with
    u3 = calloc(x, sizeof *u3);
    or the malloc "almost equivalent"
    u3 = malloc (x * sizeof *u3);
    the same as I showed for a 2D pointer.

    --
    Remove del for email
    Barry Schwarz, Jun 4, 2009
    #8
  9. Keith Thompson wrote:
    > Jean-Claude Arbaut <> writes:


    >> Someone just told me that on fr.clc ;-) Actually it's
    >> a bad habit I got from using a bad compiler that gave
    >> a warning for uncasted (mc)alloc. I can't remember
    >> which compiler it was.

    >
    > Could it have been a C++ compiler?


    Maybe. And I guess that would mean the warning is expected :)

    >>> Furthermore,
    >>> all bits zero need not be the representation of 0.0. A frequently
    >>> recommended construct is
    >>> t = calloc(n, sizeof *t);
    >>> or the malloc "almost equivalent"
    >>> t malloc (n * sizeof *t);

    >> Does it guarantee that memory is zeroed ?

    >
    > No, malloc doesn't initialize the allocated space, whereas calloc sets
    > it to all-bits-zero. But setting it to all-bits-zero doesn't
    > guarantee that all elements will be set to 0.0, since there's no
    > guarantee that all-bits-zero is a representation of all-bits-zero.
    >
    > You can probably get away with it on most (maybe all?) existing
    > systems, but it's not portable. For guaranteed portability, you need
    > to set the elements to 0.0 using a loop -- and if you're going to do
    > that anyway you might as well just use malloc rather than calloc.
    > And, depending on what you're doing with the data, you might not need
    > to set *all* the elements to 0.0.


    I think I would use calloc which would be both correct and
    faster on almost all machine, and document the lack of
    portability.
    Scarlet Pimpernel, Jun 4, 2009
    #9
  10. Barry Schwarz wrote:

    > I showed the definition of the array and the pointer above. You
    > assign allocated memory to the pointer with
    > u3 = calloc(x, sizeof *u3);
    > or the malloc "almost equivalent"
    > u3 = malloc (x * sizeof *u3);
    > the same as I showed for a 2D pointer.
    >


    Ok, actually, I had in mind a declaration of multidimensional
    array without dimensions, but it would probably never be
    necessary, since you must know the dimensions to allocate
    it.

    Another possible problem, you can declare a double[p][q][r] and pass
    it to a function that will use double[q][r][p]. I suppose
    it's still valid C ?

    And, another idea, would it be correct to use a void* like here:

    double get(int n, int p, int q, double t[n][p][q],int i, int j, int k) {
    return t[j][k];
    }

    double toto() {
    int n,p,q;
    double x;
    void *a;
    n = 100;
    p = 200;
    q = 300;
    a = malloc(n*p*q*sizeof(double));
    x = get(n,p,q,a,0,0,0);
    return x;
    }

    (gcc gives no warning)
    Scarlet Pimpernel, Jun 4, 2009
    #10
  11. Scarlet Pimpernel wrote:
    > Barry Schwarz wrote:
    >
    >> I showed the definition of the array and the pointer above. You
    >> assign allocated memory to the pointer with
    >> u3 = calloc(x, sizeof *u3);
    >> or the malloc "almost equivalent"
    >> u3 = malloc (x * sizeof *u3);
    >> the same as I showed for a 2D pointer.
    >>

    >
    > Ok, actually, I had in mind a declaration of multidimensional
    > array without dimensions, but it would probably never be
    > necessary, since you must know the dimensions to allocate
    > it.
    >
    > Another possible problem, you can declare a double[p][q][r] and pass
    > it to a function that will use double[q][r][p]. I suppose
    > it's still valid C ?
    >
    > And, another idea, would it be correct to use a void* like here:
    >
    > double get(int n, int p, int q, double t[n][p][q],int i, int j, int k) {
    > return t[j][k];
    > }
    >
    > double toto() {
    > int n,p,q;
    > double x;
    > void *a;
    > n = 100;
    > p = 200;
    > q = 300;
    > a = malloc(n*p*q*sizeof(double));
    > x = get(n,p,q,a,0,0,0);
    > return x;
    > }
    >
    > (gcc gives no warning)


    The change of pseudo in a thread may be annoying, sorry for this !
    Scarlet Pimpernel, Jun 4, 2009
    #11
  12. On Thu, 04 Jun 2009 23:59:38 +0200, Scarlet Pimpernel
    <> wrote:

    >Barry Schwarz wrote:
    >
    >> I showed the definition of the array and the pointer above. You
    >> assign allocated memory to the pointer with
    >> u3 = calloc(x, sizeof *u3);
    >> or the malloc "almost equivalent"
    >> u3 = malloc (x * sizeof *u3);
    >> the same as I showed for a 2D pointer.
    >>

    >
    >Ok, actually, I had in mind a declaration of multidimensional
    >array without dimensions, but it would probably never be
    >necessary, since you must know the dimensions to allocate
    >it.
    >
    >Another possible problem, you can declare a double[p][q][r] and pass
    >it to a function that will use double[q][r][p]. I suppose
    >it's still valid C ?


    No. It is never OK to lie to the compiler.

    In this case, a diagnostic is required and the compiler is within its
    rights to reject the program.

    >
    >And, another idea, would it be correct to use a void* like here:
    >
    >double get(int n, int p, int q, double t[n][p][q],int i, int j, int k) {
    > return t[j][k];
    >}
    >
    >double toto() {
    > int n,p,q;
    > double x;
    > void *a;
    > n = 100;
    > p = 200;
    > q = 300;
    > a = malloc(n*p*q*sizeof(double));
    > x = get(n,p,q,a,0,0,0);
    > return x;
    >}


    Syntactically it is acceptable because the fourth parameter is
    actually a pointer (even though it looks like an array) and a void
    pointer may be used as the argument to assign a value to the
    parameter. The problem of stepping through a multi-dimensional array
    as if it were a very long 1D array remains.

    >(gcc gives no warning)


    --
    Remove del for email
    Barry Schwarz, Jun 5, 2009
    #12
  13. Jean-Claude Arbaut

    JosephKK Guest

    On Wed, 03 Jun 2009 19:03:33 +0100, Flash Gordon
    <> wrote:

    >Keith Thompson wrote:
    >> Jean-Claude Arbaut <> writes:
    >>> Barry Schwarz wrote:
    >>>> On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    >>>> <> wrote:

    >> [...]
    >>>>> t = (double (*)[])calloc(n*p, sizeof(double));
    >>>> Surely you meant u here, not t.
    >>> yes
    >>>
    >>>> The cast is unnecessary.
    >>> Someone just told me that on fr.clc ;-) Actually it's
    >>> a bad habit I got from using a bad compiler that gave
    >>> a warning for uncasted (mc)alloc. I can't remember
    >>> which compiler it was.

    >>
    >> Could it have been a C++ compiler?
    >>
    >>>> Furthermore,
    >>>> all bits zero need not be the representation of 0.0. A frequently
    >>>> recommended construct is
    >>>> t = calloc(n, sizeof *t);
    >>>> or the malloc "almost equivalent"
    >>>> t malloc (n * sizeof *t);
    >>> Does it guarantee that memory is zeroed ?

    >>
    >> No, malloc doesn't initialize the allocated space, whereas calloc sets
    >> it to all-bits-zero. But setting it to all-bits-zero doesn't
    >> guarantee that all elements will be set to 0.0, since there's no
    >> guarantee that all-bits-zero is a representation of all-bits-zero.

    >
    >I know you meant "since there's no guarantee that all-bits-zero
    >represents a floating point 0.0 (or a null pointer)".


    Absolutely true. However, all zeroes is defined by IEEE-754 to be a
    valid representation of floating point 0.0, and the following machines
    are compliant: the entire X86 series, the M68K series (including
    coldfire), PPC, the NS32K series, UltraSparc and above, Alpha chips,
    at least some MIPS chips, HP PA-RISC, and probably others. Known non-
    compliant implementations include IBM 360/370/390 series, VAXen,
    probably DEC PDP-8, PDP-10, and PDP-11, CDC Cyber series, and
    certainly many more.

    Moreover, even in the non IEEE-754 compliant systems there is a
    hardware advantage to making all zeroes be a FP 0.0, and such is the
    case for VAX and probably others.

    Bottom line, not required to be portable, chances it works anyway
    very, very high.
    >
    >> You can probably get away with it on most (maybe all?) existing
    >> systems, but it's not portable. For guaranteed portability, you need
    >> to set the elements to 0.0 using a loop -- and if you're going to do
    >> that anyway you might as well just use malloc rather than calloc.
    >> And, depending on what you're doing with the data, you might not need
    >> to set *all* the elements to 0.0.

    >
    >If the OP does choose to use calloc, make sure the non-portable
    >assumption is documented just in case someone ports the SW later to an
    >unusual system where it is a problem.
    JosephKK, Jun 6, 2009
    #13
  14. On Fri, 05 Jun 2009 19:38:05 -0700,
    "JosephKK"<> wrote:

    snip

    >Absolutely true. However, all zeroes is defined by IEEE-754 to be a
    >valid representation of floating point 0.0, and the following machines
    >are compliant: the entire X86 series, the M68K series (including
    >coldfire), PPC, the NS32K series, UltraSparc and above, Alpha chips,
    >at least some MIPS chips, HP PA-RISC, and probably others. Known non-
    >compliant implementations include IBM 360/370/390 series, VAXen,


    While it is true that early IBM series do not comply with IEEE-754
    (hardly noteworthy since the 360 preceded 754 by a few decades), all
    bits zero is a representation of 0.0 and the only normalized
    representation.

    --
    Remove del for email
    Barry Schwarz, Jun 6, 2009
    #14
  15. Jean-Claude Arbaut

    Tim Rentsch Guest

    "JosephKK"<> writes:

    > On Wed, 03 Jun 2009 19:03:33 +0100, Flash Gordon
    >[snip]
    > Absolutely true. However, all zeroes is defined by IEEE-754 to be a
    > valid representation of floating point 0.0, and the following machines
    > are compliant: the entire X86 series, the M68K series (including
    > coldfire), PPC, the NS32K series, UltraSparc and above, Alpha chips,
    > at least some MIPS chips, HP PA-RISC, and probably others. Known non-
    > compliant implementations include IBM 360/370/390 series, VAXen,
    > probably DEC PDP-8, PDP-10, and PDP-11, CDC Cyber series, and
    > certainly many more.
    >
    > Moreover, even in the non IEEE-754 compliant systems there is a
    > hardware advantage to making all zeroes be a FP 0.0, and such is the
    > case for VAX and probably others.


    On the PDP-10 all-bits-zero is a 0.0 FP value. Did the PDP-8
    even have floating point? I didn't think it did.
    Tim Rentsch, Jun 6, 2009
    #15
  16. On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    <> wrote:

    > Hi,
    >
    > I can use:
    >
    > double get(int n, int p, double t[n][p], int i, int j) {
    > return t[j];
    > }
    >

    Note that using a variable (here a parameter) as an array bound is
    standard only as of C99, although it was available as an extension in
    gcc (which you say elsethread you use) years earlier.

    > and in another function
    > double (*u)[];
    > t = (double (*)[])calloc(n*p, sizeof(double));
    > a=get(n,p,u,i,j);
    >
    > Now, how would I declare u for 3 dimensions or more ?


    With the C99 or gcc Variable Length Array feature, you can _define_
    (allocate) a runtime size array just using the natural
    double u [n1] [n2] [n3] [n4]; /* or whatever */
    assuming those variables are validly set, and space is available.

    If you do want dynamic, you can declare the non-first bounds correctly
    double (*u) [n2] [n3] [n4];

    OR you can use any arbitrary (fixed) value(s)
    double (*u) [1] [1] [1];
    AS LONG AS you don't use _that_ pointer to access _components_
    (including subarrays) but only pass it to things like your get ()
    which use a (var-mod) pointer _with correct bounds_ for accesses.
    (Note that t in get() is actually a pointer, not an array.)

    Specifically, (pointer to) variable-size of T is compatible with
    (pointer to) ANY fixed-size of T, so only the 'structure' (i.e. rank
    and element type) must match not the specific bound values.

    Note that in most implementations automatic objects are allocated on
    the (single, preferred) stack, and dynamic space in a heap 'arena',
    and rather often the latter is or at least can be larger than the
    former. This applies to both fixed types (arrays with compile-time
    bounds) and variable ones, but IME people more often want to use
    variable ones to handle large (or huge) data sizes and thus more often
    run into an actual problem there.
    David Thompson, Jun 15, 2009
    #16
  17. Jean-Claude Arbaut

    Tim Rentsch Guest

    David Thompson <> writes:

    > On Wed, 03 Jun 2009 02:16:55 +0200, Jean-Claude Arbaut
    > <> wrote:
    >
    > > Hi,
    > >
    > > I can use:
    > >
    > > double get(int n, int p, double t[n][p], int i, int j) {
    > > return t[j];
    > > }
    > >

    > Note that using a variable (here a parameter) as an array bound is
    > standard only as of C99, although it was available as an extension in
    > gcc (which you say elsethread you use) years earlier.
    >
    > > and in another function
    > > double (*u)[];
    > > t = (double (*)[])calloc(n*p, sizeof(double));
    > > a=get(n,p,u,i,j);
    > >
    > > Now, how would I declare u for 3 dimensions or more ?

    >
    > With the C99 or gcc Variable Length Array feature, you can _define_
    > (allocate) a runtime size array just using the natural
    > double u [n1] [n2] [n3] [n4]; /* or whatever */
    > assuming those variables are validly set, and space is available.
    >
    > If you do want dynamic, you can declare the non-first bounds correctly
    > double (*u) [n2] [n3] [n4];


    Or all the bounds:

    double (*u)[n1][n2][n3][n4];

    and use (*u) to access the entire array, or as a parameter
    for functions taking a (double [n1][n2][n3][n4]).


    > OR you can use any arbitrary (fixed) value(s)
    > double (*u) [1] [1] [1];
    > AS LONG AS you don't use _that_ pointer to access _components_
    > (including subarrays) but only pass it to things like your get ()
    > which use a (var-mod) pointer _with correct bounds_ for accesses.
    > (Note that t in get() is actually a pointer, not an array.)


    This suggestion seems dubious. The types are compatible, yes, but.....

    > Specifically, (pointer to) variable-size of T is compatible with
    > (pointer to) ANY fixed-size of T, so only the 'structure' (i.e. rank
    > and element type) must match not the specific bound values.


    Passing an array declared with fixed bounds to a routine that
    expects a pointer-to-variable-length-array is a no-no (assuming
    the bounds don't match). The second sentence of 6.7.5.2 p 6
    says:

    If the two array types are used in a context which requires
    them to be compatible, it is undefined behavior if the two
    size specifiers evaluate to unequal values.

    Considering this condition, it's better to use one of the
    pointer-to-variable-length-array types as shown above, or
    just use a variable of type (double *) and cast it.
    Tim Rentsch, Jun 19, 2009
    #17
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mitchua
    Replies:
    5
    Views:
    2,715
    Eric J. Roode
    Jul 17, 2003
  2. =?Utf-8?B?SG96aQ==?=
    Replies:
    1
    Views:
    6,937
    Ken Cox [Microsoft MVP]
    Jun 2, 2004
  3. Adam Warner

    Flexible array member + variable length array

    Adam Warner, Feb 3, 2005, in forum: C Programming
    Replies:
    10
    Views:
    784
    S.Tobias
    Feb 10, 2005
  4. Tom
    Replies:
    3
    Views:
    198
    salsablr
    Dec 20, 2004
  5. Tuan  Bui
    Replies:
    14
    Views:
    462
    it_says_BALLS_on_your forehead
    Jul 29, 2005
Loading...

Share This Page