pointer plus an integer

Discussion in 'C Programming' started by Ivan K., Oct 11, 2007.

  1. Ivan K.

    Ivan K. Guest

    I am looking at some legacy code, which begins by
    allocating a double matrix with the dmatrix()
    function from NRC as follows:

    double **A, **augin, **augout, **aa;

    A = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    aa = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    augin = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    augout = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);

    /* ... */

    The dmatrix() function is appended below.

    At some point in the program, these lines occur.

    /* adjust indices rather than reallocate */
    for(i=2;i<=nnonm;i++) A = A[i-1] + total + addcol;
    for(i=2;i<=nnonm;i++) aa = aa[i-1] + total + addcol;
    for(i=2;i<=nnonm;i++) augin = augin[i-1] + total + addcol + 1 +
    nsims;
    for(i=2;i<=nnonm;i++) augout = augout[i-1] + total + addcol + 1
    + nsims;

    and it looks to me that what is going on here is that as A, aa,
    augin, and augout are pointers to double dimensioned arrays, then
    A is a pointer to a single array and the statement
    "A[i-1] + total + addcol" is adding an integer to
    a pointer to an array.

    Is this correct? If so, what is happening
    when one adds an integer to a pointer to an array?

    Thank you for your help;
    Ivan;

    double **dmatrix( long nrl, long nrh, long ncl, long nch)
    /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch]
    */
    {
    long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
    double **m;

    /* allocate pointers to rows */
    m=(double **) malloc((unsigned int)((nrow
    +NR_END)*sizeof(double*)));
    if (!m) nrerror("allocation failure 1 in matrix()");
    m += NR_END;
    m -= nrl;

    /* allocate rows and set pointers to them */
    m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof
    (double)));
    if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
    m[nrl] += NR_END;
    m[nrl] -= ncl;

    for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;

    /* return pointer to array of pointers to rows */
    return m;
    }
     
    Ivan K., Oct 11, 2007
    #1
    1. Advertising

  2. Ivan K.

    Jack Klein Guest

    On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    wrote in comp.lang.c:

    >
    > I am looking at some legacy code, which begins by
    > allocating a double matrix with the dmatrix()
    > function from NRC as follows:
    >
    > double **A, **augin, **augout, **aa;
    >
    > A = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    > aa = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    > augin = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    > augout = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >
    > /* ... */
    >
    > The dmatrix() function is appended below.
    >
    > At some point in the program, these lines occur.
    >
    > /* adjust indices rather than reallocate */
    > for(i=2;i<=nnonm;i++) A = A[i-1] + total + addcol;
    > for(i=2;i<=nnonm;i++) aa = aa[i-1] + total + addcol;
    > for(i=2;i<=nnonm;i++) augin = augin[i-1] + total + addcol + 1 +
    > nsims;
    > for(i=2;i<=nnonm;i++) augout = augout[i-1] + total + addcol + 1
    > + nsims;
    >
    > and it looks to me that what is going on here is that as A, aa,
    > augin, and augout are pointers to double dimensioned arrays, then
    > A is a pointer to a single array and the statement
    > "A[i-1] + total + addcol" is adding an integer to
    > a pointer to an array.
    >
    > Is this correct? If so, what is happening
    > when one adds an integer to a pointer to an array?


    No, that isn't correct. A is not a pointer to a "double dimensioned
    array". A is not a pointer to any sort of array.

    A is exactly what it is defined to be, namely a pointer to (one or
    more) pointer(s) to (one or more) double(s).

    > Thank you for your help;
    > Ivan;
    >
    > double **dmatrix( long nrl, long nrh, long ncl, long nch)
    > /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch]
    > */
    > {
    > long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
    > double **m;
    >
    > /* allocate pointers to rows */
    > m=(double **) malloc((unsigned int)((nrow
    > +NR_END)*sizeof(double*)));
    > if (!m) nrerror("allocation failure 1 in matrix()");
    > m += NR_END;
    > m -= nrl;
    >
    > /* allocate rows and set pointers to them */
    > m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof
    > (double)));
    > if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
    > m[nrl] += NR_END;
    > m[nrl] -= ncl;
    >
    > for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;
    >
    > /* return pointer to array of pointers to rows */
    > return m;
    > }


    This is hideous code, it looks like somebody tried translating FORTRAN
    to C, with the indices beginning at 1 instead of 0. And once the
    pointers have been modified, they can't be free()'d, so the program
    almost certainly creates a huge memory leak.

    Adding an integer to a pointer to any complete type works exactly the
    same way. The integer is scaled by the size of the type pointed to,
    in this case sizeof double. The result of the addition is still a
    pointer to double, and still not any kind of array.

    For a simple illustration, let's forget about how the memory is
    allocated and assume that A is a pointer to two pointers to double,
    and each one of them points to three doubles.

    A[0] points to 1.0, 2.0, 3.0
    A[1] points to 4.0, 5.0, 6.0

    Now if we execute the statement:

    A[1] = A[0] + 1;

    ....then A[1] now points to 2.0, 3.0.

    As long as the new value of A[1] is not use to access past the end of
    the original allocation, all is well. That is, A[1][0] and A[1][1]
    are accessible, but A[2] is past the end of the allocated memory.

    But there is now no way to free() the allocated memory that A[1]
    originally pointed to, unless a copy of the original pointer was saved
    somewhere else.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Oct 12, 2007
    #2
    1. Advertising

  3. Ivan K.

    Ernie Wright Guest

    Jack Klein wrote:

    > On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    > wrote in comp.lang.c:
    >
    >>I am looking at some legacy code, which begins by
    >>allocating a double matrix with the dmatrix()
    >>function from NRC as follows:
    >>
    >> double **A, **augin, **augout, **aa;
    >>
    >> A = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    >> aa = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    >> augin = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >> augout = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >>
    >> /* ... */
    >>
    >>The dmatrix() function is appended below.
    >>
    >>At some point in the program, these lines occur.
    >>
    >> /* adjust indices rather than reallocate */
    >> for(i=2;i<=nnonm;i++) A = A[i-1] + total + addcol;
    >> for(i=2;i<=nnonm;i++) aa = aa[i-1] + total + addcol;
    >> for(i=2;i<=nnonm;i++) augin = augin[i-1] + total + addcol + 1 + nsims;
    >> for(i=2;i<=nnonm;i++) augout = augout[i-1] + total + addcol + 1 + nsims;
    >>


    The first part creates matrices of maximum size.

    The second part fiddles with pointers to make the matrices appear to be
    some other (smaller) size, presumably the actual size needed at that
    point in the code.

    This is a common Fortran idiom. It's unnecessary in C, since you can
    allocate exactly the amount of memory you need at run time. In Fortran,
    an array of fixed maximum size has to be created at compile time.

    >>and it looks to me that what is going on here is that as A, aa,
    >>augin, and augout are pointers to double dimensioned arrays, then
    >>A is a pointer to a single array and the statement
    >>"A[i-1] + total + addcol" is adding an integer to
    >>a pointer to an array.
    >>
    >>Is this correct?


    Pretty much, except that the terminology is wrong. But let's ignore the
    terminology problem for a minute.

    >> If so, what is happening when one adds an integer to a pointer to
    >> an array?


    Adding an integer to a pointer increments the pointer. If p points to
    the first element in an array, then p + 2 points to the third element.

    A simplified, pseudocode version of what happens in dmatrix() would be

    double **A;

    A = malloc( storage for row pointers );
    A[ 0 ] = malloc( enough memory for the entire 2D array );
    A[ 1 ] = A[ 0 ] + ( the number of doubles in one row );
    A[ 2 ] = A[ 1 ] + ( the number of doubles in one row );
    ...

    A[0] points to the start of the memory block. A[n] points to the start
    of the n-th row.

    The part of the code after the dmatrix() calls just sets the A[n]'s
    using a different number of doubles per row.

    > No, that isn't correct. A is not a pointer to a "double dimensioned
    > array". A is not a pointer to any sort of array.
    >
    > A is exactly what it is defined to be, namely a pointer to (one or
    > more) pointer(s) to (one or more) double(s).


    Well, OK, but does that add to or subtract from the OP's confusion?
    Conceptually, A is not *merely* a pointer to a pointer to double. In
    this context, it denotes a dynamically allocated 2D "array," except that
    maybe we can't, strictly speaking, call it that. What can we call it?

    In K&R2, we have references like (5.9):

    Given the definitions

    int a[10][20];
    int *b[10];

    ....For b, however, the definition only allocates 10 pointers and
    does not initialize them; initialization must be done explicitly,
    either statically or with code. Assuming that each element of b
    does point to a twenty-element array...

    So K&R were OK with saying that b[n] is a pointer to an array.

    >>double **dmatrix( long nrl, long nrh, long ncl, long nch)
    >>/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */

    >
    > This is hideous code, it looks like somebody tried translating FORTRAN
    > to C,


    That's precisely what it is. This is adapted from a utility function
    by the same name in the first edition of Numerical Recipes in C,

    http://www.nr.com/

    which was a straight translation to K&R C from the original Numerical
    Recipes written in Fortran.

    > with the indices beginning at 1 instead of 0.


    Actually, the row indices will range between nrl and nrh, and the column
    indices will range between ncl and nch. Fortran allows you to specify
    any minimum and maximum integer index when you declare an array.

    > And once the pointers have been modified, they can't be free()'d, so
    > the program almost certainly creates a huge memory leak.


    Only one block of memory is allocated per matrix. The pointer to it is
    stored as the pointer to the first row, which isn't modified in the
    fiddling with the pointers, and recovered later in a matching call to
    free_dmatrix(), which must also take nrl as an argument so that it can
    undo the indexing offset.

    It's still hideous, but it only leaks if they forget to free_dmatrix(),
    or (possibly) if they pass it the wrong nrl.

    - Ernie http://home.comcast.net/~erniew
     
    Ernie Wright, Oct 12, 2007
    #3
  4. Ivan K.

    JimS Guest

    On Thu, 11 Oct 2007 21:43:52 -0500, Jack Klein <>
    wrote:

    >On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    >wrote in comp.lang.c:
    >
    >>
    >> I am looking at some legacy code, which begins by
    >> allocating a double matrix with the dmatrix()
    >> function from NRC as follows:
    >>
    >> double **A, **augin, **augout, **aa;
    >>
    >> A = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    >> aa = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    >> augin = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >> augout = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >>
    >> /* ... */
    >>
    >> The dmatrix() function is appended below.
    >>
    >> At some point in the program, these lines occur.
    >>
    >> /* adjust indices rather than reallocate */
    >> for(i=2;i<=nnonm;i++) A = A[i-1] + total + addcol;
    >> for(i=2;i<=nnonm;i++) aa = aa[i-1] + total + addcol;
    >> for(i=2;i<=nnonm;i++) augin = augin[i-1] + total + addcol + 1 +
    >> nsims;
    >> for(i=2;i<=nnonm;i++) augout = augout[i-1] + total + addcol + 1
    >> + nsims;
    >>
    >> and it looks to me that what is going on here is that as A, aa,
    >> augin, and augout are pointers to double dimensioned arrays, then
    >> A is a pointer to a single array and the statement
    >> "A[i-1] + total + addcol" is adding an integer to
    >> a pointer to an array.
    >>
    >> Is this correct? If so, what is happening
    >> when one adds an integer to a pointer to an array?

    >
    >No, that isn't correct. A is not a pointer to a "double dimensioned
    >array". A is not a pointer to any sort of array.
    >
    >A is exactly what it is defined to be, namely a pointer to (one or
    >more) pointer(s) to (one or more) double(s).
    >
    >> Thank you for your help;
    >> Ivan;
    >>
    >> double **dmatrix( long nrl, long nrh, long ncl, long nch)
    >> /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch]
    >> */
    >> {
    >> long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
    >> double **m;
    >>
    >> /* allocate pointers to rows */
    >> m=(double **) malloc((unsigned int)((nrow
    >> +NR_END)*sizeof(double*)));
    >> if (!m) nrerror("allocation failure 1 in matrix()");
    >> m += NR_END;
    >> m -= nrl;
    >>
    >> /* allocate rows and set pointers to them */
    >> m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof
    >> (double)));
    >> if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
    >> m[nrl] += NR_END;
    >> m[nrl] -= ncl;
    >>
    >> for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;
    >>
    >> /* return pointer to array of pointers to rows */
    >> return m;
    >> }

    >
    >This is hideous code, it looks like somebody tried translating FORTRAN
    >to C, with the indices beginning at 1 instead of 0. And once the
    >pointers have been modified, they can't be free()'d, so the program
    >almost certainly creates a huge memory leak.


    It looks like sample code from Numerical Recipes in C.
    To get an array indexed from 1-10 instead of 0-9 they do

    double *m = malloc(10* sizeof *m);
    m -= 1;

    Of course, that's undefined behaviour.

    Jim
     
    JimS, Oct 12, 2007
    #4
  5. Ivan K.

    Wade Ward Guest

    "Jack Klein" <> wrote in message
    news:...
    > On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    > wrote in comp.lang.c:
    >
    >>
    >> I am looking at some legacy code, which begins by
    >> allocating a double matrix with the dmatrix()
    >> function from NRC as follows:
    >>
    >> double **A, **augin, **augout, **aa;
    >>
    >> A = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    >> aa = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3);
    >> augin = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >> augout = dmatrix(1, MAXNSTU+1, 1, MAXCOV+MAXCOVLOC+3+MAXSIMS);
    >>
    >> /* ... */
    >>
    >> The dmatrix() function is appended below.
    >>
    >> At some point in the program, these lines occur.
    >>
    >> /* adjust indices rather than reallocate */
    >> for(i=2;i<=nnonm;i++) A = A[i-1] + total + addcol;
    >> for(i=2;i<=nnonm;i++) aa = aa[i-1] + total + addcol;
    >> for(i=2;i<=nnonm;i++) augin = augin[i-1] + total + addcol + 1 +
    >> nsims;
    >> for(i=2;i<=nnonm;i++) augout = augout[i-1] + total + addcol + 1
    >> + nsims;
    >>
    >> and it looks to me that what is going on here is that as A, aa,
    >> augin, and augout are pointers to double dimensioned arrays, then
    >> A is a pointer to a single array and the statement
    >> "A[i-1] + total + addcol" is adding an integer to
    >> a pointer to an array.
    >>
    >> Is this correct? If so, what is happening
    >> when one adds an integer to a pointer to an array?

    >
    > No, that isn't correct. A is not a pointer to a "double dimensioned
    > array". A is not a pointer to any sort of array.
    >
    > A is exactly what it is defined to be, namely a pointer to (one or
    > more) pointer(s) to (one or more) double(s).
    >
    >> Thank you for your help;
    >> Ivan;
    >>
    >> double **dmatrix( long nrl, long nrh, long ncl, long nch)
    >> /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch]
    >> */
    >> {
    >> long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
    >> double **m;
    >>
    >> /* allocate pointers to rows */
    >> m=(double **) malloc((unsigned int)((nrow
    >> +NR_END)*sizeof(double*)));
    >> if (!m) nrerror("allocation failure 1 in matrix()");
    >> m += NR_END;
    >> m -= nrl;
    >>
    >> /* allocate rows and set pointers to them */
    >> m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof
    >> (double)));
    >> if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
    >> m[nrl] += NR_END;
    >> m[nrl] -= ncl;
    >>
    >> for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;
    >>
    >> /* return pointer to array of pointers to rows */
    >> return m;
    >> }

    >
    > This is hideous code, it looks like somebody tried translating FORTRAN
    > to C, with the indices beginning at 1 instead of 0. And once the
    > pointers have been modified, they can't be free()'d, so the program
    > almost certainly creates a huge memory leak.


    It's equally or more hideous as fortran. I'm guessing matlab or something.
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 13, 2007
    #5
  6. Jack Klein wrote:
    > On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    > wrote in comp.lang.c:
    >
    >> I am looking at some legacy code, which begins by
    >> allocating a double matrix with the dmatrix()
    >> function from NRC as follows:

    ....
    >> double **dmatrix( long nrl, long nrh, long ncl, long nch)
    >> /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch]
    >> */
    >> {
    >> long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
    >> double **m;
    >>
    >> /* allocate pointers to rows */
    >> m=(double **) malloc((unsigned int)((nrow
    >> +NR_END)*sizeof(double*)));
    >> if (!m) nrerror("allocation failure 1 in matrix()");
    >> m += NR_END;
    >> m -= nrl;
    >>
    >> /* allocate rows and set pointers to them */
    >> m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof
    >> (double)));
    >> if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
    >> m[nrl] += NR_END;
    >> m[nrl] -= ncl;
    >>
    >> for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;
    >>
    >> /* return pointer to array of pointers to rows */
    >> return m;
    >> }

    >
    > This is hideous code, it looks like somebody tried translating FORTRAN
    > to C, with the indices beginning at 1 instead of 0.


    Correct. That's exactly the historical development of the NRC (Numerical
    Recipes in C) library. I've translated a fair number of their
    "Fortran-inspired C" routines into "native C" style; the effort was
    significant; avoiding off-by-one errors in loops required constant
    vigilance - I can understand why someone not very familiar with C might
    have chosen this awful work-around to avoid having to do that same work.

    But someone not very familiar with C shouldn't have been writing
    "Numerical Recipes in C". I own the book, and I find it very useful, but
    only because it contains detailed information about a lot of algorithms
    that are relevant to my interests; not because the source code is well
    written.

    > And once the
    > pointers have been modified, they can't be free()'d, so the program
    > almost certainly creates a huge memory leak.


    The Numerical Recipes library provides routines for both allocating and
    deallocating arrays built in this style. It's precisely as easy to
    forget to call the array deallocation function as it is to forget to
    call free(). I don't see any increased risk of a memory leak.
     
    James Kuyper Jr., Oct 13, 2007
    #6
  7. Ivan K.

    Wade Ward Guest

    "James Kuyper Jr." <> wrote in message
    news:7z5Qi.793$hI1.195@trndny06...
    > Jack Klein wrote:
    >> On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    >> wrote in comp.lang.c:
    >>
    >>> I am looking at some legacy code, which begins by
    >>> allocating a double matrix with the dmatrix()
    >>> function from NRC as follows:

    > ...
    >>> double **dmatrix( long nrl, long nrh, long ncl, long nch)
    >>> /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch]
    >>> */
    >>> {
    >>> long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
    >>> double **m;
    >>>
    >>> /* allocate pointers to rows */
    >>> m=(double **) malloc((unsigned int)((nrow
    >>> +NR_END)*sizeof(double*)));
    >>> if (!m) nrerror("allocation failure 1 in matrix()");
    >>> m += NR_END;
    >>> m -= nrl;
    >>>
    >>> /* allocate rows and set pointers to them */
    >>> m[nrl]=(double *) malloc((unsigned int)((nrow*ncol+NR_END)*sizeof
    >>> (double)));
    >>> if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
    >>> m[nrl] += NR_END;
    >>> m[nrl] -= ncl;
    >>>
    >>> for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;
    >>>
    >>> /* return pointer to array of pointers to rows */
    >>> return m;
    >>> }

    >>
    >> This is hideous code, it looks like somebody tried translating FORTRAN
    >> to C, with the indices beginning at 1 instead of 0.

    >
    > Correct. That's exactly the historical development of the NRC (Numerical
    > Recipes in C) library. I've translated a fair number of their
    > "Fortran-inspired C" routines into "native C" style; the effort was
    > significant; avoiding off-by-one errors in loops required constant
    > vigilance - I can understand why someone not very familiar with C might
    > have chosen this awful work-around to avoid having to do that same work.

    No, incorrect. This pointer-infested slop was never fortran.

    The fortran would look more like:
    real, allocatable :: A:),:)
    ....
    allocate (A(rows,columns))
    > But someone not very familiar with C shouldn't have been writing
    > "Numerical Recipes in C". I own the book, and I find it very useful, but
    > only because it contains detailed information about a lot of algorithms
    > that are relevant to my interests; not because the source code is well
    > written.
    >
    >> And once the
    >> pointers have been modified, they can't be free()'d, so the program
    >> almost certainly creates a huge memory leak.

    >
    > The Numerical Recipes library provides routines for both allocating and
    > deallocating arrays built in this style. It's precisely as easy to forget
    > to call the array deallocation function as it is to forget to call free().
    > I don't see any increased risk of a memory leak.

    In fortran, the common C extension, all you need to do is:
    deallocate (A)
    , no free's, malloc's or leaks.
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 15, 2007
    #7
  8. Ivan K.

    Ernie Wright Guest

    JimS wrote:

    > It looks like sample code from Numerical Recipes in C.


    It was clearly derived from that book, but it differs from the original
    NRC code.

    > To get an array indexed from 1-10 instead of 0-9 they do
    >
    > double *m = malloc(10* sizeof *m);
    > m -= 1;
    >
    > Of course, that's undefined behaviour.


    The book was written before C89.

    - Ernie http://home.comcast.net/~erniew
     
    Ernie Wright, Oct 15, 2007
    #8
  9. Ivan K.

    Ernie Wright Guest

    Wade Ward wrote:

    > "James Kuyper Jr." <> wrote in message
    > news:7z5Qi.793$hI1.195@trndny06...
    >
    >>Jack Klein wrote:
    >>
    >>>This is hideous code, it looks like somebody tried translating FORTRAN
    >>>to C, with the indices beginning at 1 instead of 0.

    >>
    >>Correct.

    >
    > No, incorrect. This pointer-infested slop was never fortran.
    >
    > The fortran would look more like:
    > real, allocatable :: A:),:)
    > ...
    > allocate (A(rows,columns))


    That's Fortran 90. The original Numerical Recipes was written using
    Fortran 77.

    - Ernie http://home.comcast.net/~erniew
     
    Ernie Wright, Oct 15, 2007
    #9
  10. Ivan K.

    Ben Pfaff Guest

    Ernie Wright <> writes:

    >> It looks like sample code from Numerical Recipes in C.
    >> [...]
    >> double *m = malloc(10* sizeof *m);
    >> m -= 1;
    >>
    >> Of course, that's undefined behaviour.

    >
    > The book was written before C89.


    The latest edition has a discussion of the issue and a fix for
    the code, although the authors do not exactly take a
    comp.lang.c-approved attitude toward it.
    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
     
    Ben Pfaff, Oct 15, 2007
    #10
  11. Ivan K.

    Wade Ward Guest

    "Ernie Wright" <> wrote in message
    news:p...
    > Wade Ward wrote:
    >
    >> "James Kuyper Jr." <> wrote in message
    >> news:7z5Qi.793$hI1.195@trndny06...
    >>
    >>>Jack Klein wrote:
    >>>
    >>>>This is hideous code, it looks like somebody tried translating FORTRAN
    >>>>to C, with the indices beginning at 1 instead of 0.
    >>>
    >>>Correct.

    >>
    >> No, incorrect. This pointer-infested slop was never fortran.
    >>
    >> The fortran would look more like:
    >> real, allocatable :: A:),:)
    >> ...
    >> allocate (A(rows,columns))

    >
    > That's Fortran 90. The original Numerical Recipes was written using
    > Fortran 77.

    The biggest attraction to f77 was the dynamically allocatable array, at
    least so says Richard Maine. If that was originally f77, the author clearly
    was not using the strength of the syntax. Hideous code is somehow a
    metasyntactic constant.
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 15, 2007
    #11
  12. Ivan K.

    Wade Ward Guest

    "Ben Pfaff" <> wrote in message
    news:...
    > Ernie Wright <> writes:
    >
    >>> It looks like sample code from Numerical Recipes in C.
    >>> [...]
    >>> double *m = malloc(10* sizeof *m);
    >>> m -= 1;
    >>>
    >>> Of course, that's undefined behaviour.

    >>
    >> The book was written before C89.

    >
    > The latest edition has a discussion of the issue and a fix for
    > the code, although the authors do not exactly take a
    > comp.lang.c-approved attitude toward it.

    If the authors *ever* approved of that code, it would be proof of their own
    incompetence.

    char a[]="\n .CJacehknorstu";int putchar(int);int main(void)
    {unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;
    for(;p+=!*p;*p/=4)
    switch(0[p]&3)case 0:

    {
    system("pause");
    return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);
    break;}}}
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 15, 2007
    #12
  13. Wade Ward wrote:
    > "James Kuyper Jr." <> wrote in message
    > news:7z5Qi.793$hI1.195@trndny06...

    ....
    >> Correct. That's exactly the historical development of the NRC (Numerical
    >> Recipes in C) library. I've translated a fair number of their
    >> "Fortran-inspired C" routines into "native C" style; the effort was
    >> significant; avoiding off-by-one errors in loops required constant
    >> vigilance - I can understand why someone not very familiar with C might
    >> have chosen this awful work-around to avoid having to do that same work.

    > No, incorrect. This pointer-infested slop was never fortran.


    I didn't say that it was. That pointer-infested slop was created during
    the translation process from Fortran to C, apparently by someone far
    more familiar with Fortran than with C. It's a clever, but fundamentally
    misguided, attempt to create something in C that can be used in a manner
    similar to Fortran arrays, thereby simplifying the translation of
    Fortran code which indexed those "arrays".

    The cost of this design decision was that it made the code hard to
    understand for more experienced C programmers, and added in unnecessary
    complexity related to allocation and deallocation of those arrays.

    > The fortran would look more like:
    > real, allocatable :: A:),:)


    I have a fair amount of experience with Fortran, but it ended a long
    time ago, before I ever used a compiler supporting the features you're
    using in that statement. I strongly suspect that the original Fortran
    version of the Numerical Recipes library also pre-dates those features;
    or at least, was written to be backwardly compatible with compilers that
    did not yet support them.
     
    James Kuyper Jr., Oct 15, 2007
    #13
  14. Ivan K.

    Ernie Wright Guest

    Wade Ward wrote:

    > "Ernie Wright" <> wrote in message
    > news:p...
    >
    >>Wade Ward wrote:
    >>
    >>>The fortran would look more like:
    >>>real, allocatable :: A:),:)
    >>>...
    >>>allocate (A(rows,columns))

    >>
    >>That's Fortran 90. The original Numerical Recipes was written using
    >>Fortran 77.

    >
    > The biggest attraction to f77 was the dynamically allocatable array, at
    > least so says Richard Maine.


    You're misremembering what he said, or he misspoke. f77 doesn't have
    allocatable arrays. It doesn't even have lowercase source.

    - Ernie http://home.comcast.net/~erniew
     
    Ernie Wright, Oct 15, 2007
    #14
  15. Ivan K.

    Wade Ward Guest

    "James Kuyper Jr." <> wrote in message
    news:gNHQi.699$H92.359@trnddc07...
    > Wade Ward wrote:
    >> "James Kuyper Jr." <> wrote in message
    >> news:7z5Qi.793$hI1.195@trndny06...

    > ...
    >>> Correct. That's exactly the historical development of the NRC (Numerical
    >>> Recipes in C) library. I've translated a fair number of their
    >>> "Fortran-inspired C" routines into "native C" style; the effort was
    >>> significant; avoiding off-by-one errors in loops required constant
    >>> vigilance - I can understand why someone not very familiar with C might
    >>> have chosen this awful work-around to avoid having to do that same work.

    >> No, incorrect. This pointer-infested slop was never fortran.

    >
    > I didn't say that it was. That pointer-infested slop was created during
    > the translation process from Fortran to C, apparently by someone far more
    > familiar with Fortran than with C. It's a clever, but fundamentally
    > misguided, attempt to create something in C that can be used in a manner
    > similar to Fortran arrays, thereby simplifying the translation of Fortran
    > code which indexed those "arrays".
    >
    > The cost of this design decision was that it made the code hard to
    > understand for more experienced C programmers, and added in unnecessary
    > complexity related to allocation and deallocation of those arrays.
    >
    >> The fortran would look more like:
    >> real, allocatable :: A:),:)

    >
    > I have a fair amount of experience with Fortran, but it ended a long time
    > ago, before I ever used a compiler supporting the features you're using in
    > that statement. I strongly suspect that the original Fortran version of
    > the Numerical Recipes library also pre-dates those features; or at least,
    > was written to be backwardly compatible with compilers that did not yet
    > support them.

    That's probably a fair run-down on what happened.
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 15, 2007
    #15
  16. Ivan K.

    Wade Ward Guest

    "Ernie Wright" <> wrote in message
    news:...
    > Wade Ward wrote:
    >
    >> "Ernie Wright" <> wrote in message
    >> news:p...
    >>
    >>>Wade Ward wrote:
    >>>
    >>>>The fortran would look more like:
    >>>>real, allocatable :: A:),:)
    >>>>...
    >>>>allocate (A(rows,columns))
    >>>
    >>>That's Fortran 90. The original Numerical Recipes was written using
    >>>Fortran 77.

    >>
    >> The biggest attraction to f77 was the dynamically allocatable array, at
    >> least so says Richard Maine.

    >
    > You're misremembering what he said, or he misspoke. f77 doesn't have
    > allocatable arrays. It doesn't even have lowercase source.

    f77 is fixed-form, where source needs to be in a certain column or face
    terrible consequences. I've only seen it as upper-case, and it looks like
    shouting. f90 allowed free-form, with much more-relaxed rules for
    appearance. I don't think I remember wrongly about Richard's reasons for
    using f77, and he seems to be a walking fortran encyclopedia.

    f2003 allows interoperabiltiy with C, but there is no full-fledged compiler
    yet available. I don't know where the rub is, as far as getting a compliant
    implementation (I use f95). If I had to guess, I would say it's with the
    object-oriented stuff. There's also head-scratchers with C interop. People
    are constructively discussing issues having to do with f2008.
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 15, 2007
    #16
  17. Ivan K.

    Wade Ward Guest

    Re: pointer plus an integer && castingt an integer to a pointer.

    [snipped from elsewhere]

    >>I can't see how to cast an integer to a pointer.


    > You can't. Fortran doesn't do that - not even with the C interop stuff.
    > Of course,you can always play around with TRANSFER, but recall that the
    > standard says that the resulting values are undefined when you type
    > cheat with TRANSFER. And you can do it in C.


    You can't do it portably in C, either. I believe you can memcpy() in
    to an (unsigned char *) and back again. If sizeof(int) >= sizeof(void*)
    you might be able to do the cast, but the use of the value of the
    int is non-portable. Those writing large model x86 code, and
    who try to do such casts, know all about this one.

    >> cptr = C_PTR(p+1)


    > I suppose you are trying to use a structure constructor here. You can't
    > do that with C_PTR as it has (intentionally) private components. The
    > whole point of private components is to keep you from fiddling with the
    > innards. You can't write a structure constructor for a private component
    > - you don't even know what the components are. Now maybe you know what a
    > C pointer better look like inside, but accordingh to the Fortran
    > compiler, you don't know.


    From K&R2 (close, but not exactly, the C89 standard) A6.6:

    "Certain other conversions involving pointers and integers are
    permitted, but have implementation defined aspects. They must
    be specified by an explicit type-conversion operator, or cast."

    "A pointer may be converted to an integral type large enough to
    hold it; the required size is implementation-dependent. The
    mapping function is also implementation dependent."

    "An object of integral type may be explicitly converted to a
    pointer. The mapping always carries a sufficiently wide integer
    converted from a pointer back to the same pointer, but is
    otherwise implementation-dependent."

    Can someone in the know comment on the above?
    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 15, 2007
    #17
  18. Ivan K.

    Ernie Wright Guest

    Wade Ward wrote:

    > Ernie Wright wrote:
    >> Wade Ward wrote:
    >>> Ernie Wright wrote:
    >>>
    >>>>That's Fortran 90. The original Numerical Recipes was written using
    >>>>Fortran 77.
    >>>
    >>>The biggest attraction to f77 was the dynamically allocatable array, at
    >>>least so says Richard Maine.

    >>
    >>You're misremembering what he said, or he misspoke. f77 doesn't have
    >>allocatable arrays. It doesn't even have lowercase source.

    >
    > f77 is fixed-form, where source needs to be in a certain column or face
    > terrible consequences. I've only seen it as upper-case, and it looks like
    > shouting. f90 allowed free-form, with much more-relaxed rules for
    > appearance.


    Yeah, I know all that. Fortran was my second language, and f77 was the
    language used in my first computer science course in college.

    It didn't have allocatable arrays.

    > I don't think I remember wrongly about Richard's reasons for
    > using f77, and he seems to be a walking fortran encyclopedia.


    There's no reason to guess. Plenty of websites list the major features
    added to f90.

    - Ernie http://home.comcast.net/~erniew
     
    Ernie Wright, Oct 16, 2007
    #18
  19. Ivan K.

    Wade Ward Guest

    "Ernie Wright" <> wrote in message
    news:...
    > Wade Ward wrote:


    > Yeah, I know all that. Fortran was my second language, and f77 was the
    > language used in my first computer science course in college.

    Me too. We didn't get very far with the material.

    > It didn't have allocatable arrays.
    >
    >> I don't think I remember wrongly about Richard's reasons for using f77,
    >> and he seems to be a walking fortran encyclopedia.

    >
    > There's no reason to guess. Plenty of websites list the major features
    > added to f90.

    Yeah, you're right. I wonder if I remember wrong or Richard mistyped....
    http://en.wikipedia.org/wiki/Fortran#FORTRAN_77

    --
    wade ward
    "Nicht verzagen, Bruder Grinde fragen."
     
    Wade Ward, Oct 16, 2007
    #19
  20. On Fri, 12 Oct 2007 02:58:08 -0400, Ernie Wright <>
    wrote:

    > Jack Klein wrote:
    >
    > > On Thu, 11 Oct 2007 11:42:00 -0700, "Ivan K." <>
    > > wrote in comp.lang.c:

    <snip: code from Numerical Recipes in C>
    > The first part creates matrices of maximum size.
    >
    > The second part fiddles with pointers to make the matrices appear to be
    > some other (smaller) size, presumably the actual size needed at that
    > point in the code.
    >
    > This is a common Fortran idiom. It's unnecessary in C, since you can
    > allocate exactly the amount of memory you need at run time. In Fortran,
    > an array of fixed maximum size has to be created at compile time.
    >

    <OT> It was necessary in early versions of the language then known as
    FORTRAN (all caps). Since the 1990 version, when the name was changed
    to Fortran, you can have local (non-COMMON, non-SAVEd) arrays with
    size determined at routine entry, much like the VLA types added to C
    in C99, somewhat confusing called 'automatic'; and also 'allocatable'
    arrays which are dynamically allocated to a runtime-computable size,
    and deallocated etc., like C malloc&friends except that the bounds are
    automatically remembered for you and used, and it never leaks (since
    some minor fixes in F95 IIRC), although there are some contexts you
    can't use allocatable until post-F95 (a TR to F95, folded into F03).

    <snip rest>
    - formerly david.thompson1 || achar(64) || worldnet.att.net
     
    David Thompson, Oct 29, 2007
    #20
    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. The LoxFather

    C plus plus vs C Sharp

    The LoxFather, Aug 9, 2003, in forum: C++
    Replies:
    23
    Views:
    9,361
  2. The LoxFather

    C plus plus vs C Sharp

    The LoxFather, Aug 9, 2003, in forum: C Programming
    Replies:
    23
    Views:
    1,449
  3. Rahul
    Replies:
    9
    Views:
    446
    Andrey Tarasevich
    Mar 25, 2008
  4. Replies:
    11
    Views:
    517
    Richard Bos
    May 8, 2008
  5. furqan shaikh

    c plus plus code comparator

    furqan shaikh, Nov 7, 2008, in forum: C++
    Replies:
    6
    Views:
    846
    red floyd
    Nov 12, 2008
Loading...

Share This Page