Thread: Indexes of arrays in C starting with 1

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    3

    Indexes of arrays in C starting with 1

    Hey all,

    I'm programming a scientific application, namely, a Finite Element solver in ANSI C. The Finite Element research community is totally addicted to Fortran codes, due to some reasons; for instance its ability and ease when dealing with matrices/vectors and also its flexibility in the indexes of the arrays, since you can use every set of integers as indices.

    In this kind of application, one must carry several loops over the elements and nodes of a mesh (basically a triangulation of a domain), and the numbering of these entities starts with one ! So, when programming Finite Element in C, I must every time concern with subtracting 1 to access the positions of my array, when in Fortran I would just use the numbering of the nodes directly as indexes.

    The question is: Is there anyway to mask the indexing of vectors in C? I first thought about just providing a function double* AllocateVector(int n) that would actually allocate a (n+1) components vector and set the 0 component to 0 and remain it unused, since only one component more for each vector is not a problem. But this is not valid for matrices, sice an (nxn) matrix would have (2n+1) more entries, and this could represent a great amount of memory more.

    Or maybe there is some way to "overload the operator ()" without actually using operator overloading (since the program is C, and not C++) and when I write A(i,j), it converts to A[i-1][j-1].

    Is there some way to do this ? I hope you could understand my problem.

    Thanks in Advance,
    Rafael March.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You don't need to mask anything. Allocate one more space than you need, use less than comparisons, and start at 1.


    Then wonder why everyone is swearing at you for using C arrays wrong...


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Oct 2009
    Posts
    3
    This is not what I would call an useful reply.

    I do understand that the numbering of arrays in C has its advantages, but to this kind of application it can be really inconvenient. It can introduce several bugs, since you have always to wonder wether you have or haven't to subtract 1 to the index.

    What do you suggest ? That I give up writing my code in C, a language that I really feel confortable with, and surrender to Fortran ? I hope there is another way...

    Waiting for suggestions.

    Regards,
    Rafael.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by RafaelMarch View Post
    I do understand that the numbering of arrays in C has its advantages, but to this kind of application it can be really inconvenient. It can introduce several bugs, since you have always to wonder wether you have or haven't to subtract 1 to the index.
    That's why you should be consistent. If you're going to not use arrays correctly, don't use them correctly all the time in your program.
    Quote Originally Posted by RafaelMarch View Post
    What do you suggest ? That I give up writing my code in C, a language that I really feel confortable with, and surrender to Fortran ?
    I suggest you use them the way they're supposed to be used. I'm not sure what your real argument for using them incorrectly is, other than "I don't feel like translating from 1 to 0"!

    Your excuse, or post or whatever this is, is basically "I don't feel like making the translation from 1 to 0. Someone tell me how I can use C arrays incorrectly!", and when you're told how you can get around it, you say "That's not helpful."



    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Oct 2009
    Posts
    3
    Yeah, the solution your proposed was just I thought (and wrote) first. But, as I also wrote, an nxn matrix will have 2n+1 more entries, so a 100.000x100.000 matrix would have 200.001 more entries. This can represent a gross amount of memory extra available.

    Let's change my question a little bit. For a specific matrix A, i could write:

    #define B(i,j) B[i-1][j-1]

    This is a way that I could achieve this. Now I have the flexibility to use the "operator" (..,..) when I want. Is there a way to do this for ALL the matrices ?

    Regards,
    Rafael.

  6. #6
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    First of all, let me say that in most applications 0-indices are easiest. I rarely have to "subtract one", but I often had to "add one" in 1-based indices. The only reason you'd have to commonly subtract one is because some data uses 1-based indices. I've had it with certain 3D mesh file formats. I prefer to just subtract one from everything, then.

    If you really, really want what you were talking about, use C++ and create a class or write your own "C-style" type: a structure with an init and destroy function and accessing functions. Like:
    matrix_init(&matrix);
    matrix_get(&matrix, 1, 1);
    matrix_destroy(&matrix);

    That's the best way to do such a thing in C, in my opinion.

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I still can't understand why it is you think you need to use the arrays incorrectly. What are you doing? Are you trying to make your code portable to FORTRAN? Are you trying to convert their code to C? I just can't understand why you think you can't just use arrays the way they were meant to be used.


    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Can you not simply pre-decrement the base address of the vector or array? I.e. make it point to -1. If it's 2-dimensional, then the matrix should be n (rows) of pre-decremented pointers to the rows. I don't know off hand any way to do this in a contiguous multi dimensional array though.

    double array[10];
    double *array_base = &array[-1]

    use array_base[1] ... index 1 based

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by nonoob View Post
    Can you not simply pre-decrement the base address of the vector or array? I.e. make it point to -1. If it's 2-dimensional, then the matrix should be n (rows) of pre-decremented pointers to the rows. I don't know off hand any way to do this in a contiguous multi dimensional array though.

    double array[10];
    double *array_base = &array[-1]

    use array_base[1] ... index 1 based
    I don't think that's defined behavior, and if it "worked" you might overwrite some other variable's memory doing that.

  10. #10
    Registered User
    Join Date
    Nov 2008
    Posts
    75
    Quote Originally Posted by whiteflags View Post
    I don't think that's defined behavior, and if it "worked" you might overwrite some other variable's memory doing that.
    Yes, it _is_ undefined. 1 after the end(not to work with it, but to point to it), ok, 1 before the beginning, ??.

  11. #11
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by whiteflags View Post
    I don't think that's defined behavior, and if it "worked" you might overwrite some other variable's memory doing that.
    Why would it be undefined? I disagree. Unless the address underflows, which may happen but is fairly unlikely in common processors, it's probably defined just fine.
    Code:
    double *ptr = &array[-1];
    double *ptr = (double*)(((char*)array) - sizeof(double*));
    Is the same. So while we get the pointer to point before the actually array, we don't actually change something until we dereference ptr. If we dereference ptr[1], and never ptr[0], we simply change array[0]. Why would this be undefined?

    Well, like I said, if array has an address of less than sizeof(double*), the subtraction would underflow which results in undefined behaviour... But why would it, in other cases?

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612

  13. #13
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by RafaelMarch View Post
    I'm programming a scientific application, namely, a Finite Element solver in ANSI C. The Finite Element research community is totally addicted to Fortran codes, due to some reasons; for instance its ability and ease when dealing with matrices/vectors and also its flexibility in the indexes of the arrays, since you can use every set of integers as indices.

    In this kind of application, one must carry several loops over the elements and nodes of a mesh (basically a triangulation of a domain), and the numbering of these entities starts with one ! So, when programming Finite Element in C, I must every time concern with subtracting 1 to access the positions of my array, when in Fortran I would just use the numbering of the nodes directly as indexes.

    The question is: Is there anyway to mask the indexing of vectors in C? I first thought about just providing a function double* AllocateVector(int n) that would actually allocate a (n+1) components vector and set the 0 component to 0 and remain it unused, since only one component more for each vector is not a problem. But this is not valid for matrices, sice an (nxn) matrix would have (2n+1) more entries, and this could represent a great amount of memory more.

    Or maybe there is some way to "overload the operator ()" without actually using operator overloading (since the program is C, and not C++) and when I write A(i,j), it converts to A[i-1][j-1].

    Is there some way to do this ? I hope you could understand my problem.
    What you're wanting to do then is a minimal port from fortran to C++. You're only going as far as translating the syntax from one language to the other. This is the fastest way to get something going when you possibly don't understand all of what the original code is doing. It wont guarantee no bugs are introduced in the process, but it should be pretty close to a perfect replication.
    That said, in the long run it's going to likely be worse.
    What I would recommend is doing a full port of the code, including reimplementing all algorithms in such a way that their indexes start at zero instead.
    If you come across bits that are too hard for you to do this for, you can post them here. Or if the resulting code seems to have a bug, you can post if here.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Vertex Arrays
    By Shamino in forum Game Programming
    Replies: 2
    Last Post: 01-08-2006, 01:24 AM
  2. Need Help With 3 Parallel Arrays Selction Sort
    By slickwilly440 in forum C++ Programming
    Replies: 4
    Last Post: 11-19-2005, 10:47 PM
  3. Building B-Tree from Arrays
    By 0rion in forum C Programming
    Replies: 1
    Last Post: 04-09-2005, 02:34 AM
  4. Help with arrays and pointers please...
    By crazyeyesz28 in forum C++ Programming
    Replies: 8
    Last Post: 03-17-2005, 01:48 PM
  5. writing arrays to files
    By Zaarin in forum C++ Programming
    Replies: 1
    Last Post: 08-30-2001, 11:26 PM