Negative indices to a vector: Valid?

Discussion in 'C Programming' started by Joakim Hove, Dec 22, 2005.

  1. Joakim Hove

    Joakim Hove Guest

    Hello,

    I have the following code:

    #define N 99
    double *ptr;
    double *storage;
    int index;

    storage = calloc(N , sizeof(double));
    ptr = &storage[N/2];
    ...
    ...
    ...
    free(storage);


    Now ptr points into the middle of the allocated memory area, and I can
    access elements in the array as ptr[index], where index is a *signed*
    variable which can take the values -N/2,...N/2. Is this legal
    behaviour? Or should the index operator only be given unsigned
    arguments?

    I have tried using a couple of different compilers on Linux and IRIX,
    and it seems to work, but it does give me a slightly queasy feeling.


    Regards

    Joakim

    --
    Joakim Hove
    hove AT ntnu.no /
    Tlf: +47 (55 5)8 27 13 / Stabburveien 18
    Fax: +47 (55 5)8 94 40 / N-5231 Paradis
    http://www.ift.uib.no/~hove/ / 55 91 28 18 / 92 68 57 04
    Joakim Hove, Dec 22, 2005
    #1
    1. Advertising

  2. This is perfectly legal. The array index is treated as a signed integer
    in C.

    a is a shorthand way of writing
    a + sizeof(a)*i

    Thus if i is negative, the final entry addressed would be before a[0].

    --
    EventStudio System Designer 2.5 - http://www.EventHelix.com/EventStudio
    Sequence Diagram Based Real-time and Embedded System Design Tool
    EventHelix.com, Dec 22, 2005
    #2
    1. Advertising

  3. Joakim Hove

    Flash Gordon Guest

    Joakim Hove wrote:
    > Hello,
    >
    > I have the following code:
    >
    > #define N 99
    > double *ptr;
    > double *storage;
    > int index;
    >
    > storage = calloc(N , sizeof(double));


    All bits 0 (which is what calloc provides) is *not* guaranteed to
    represent a floating point 0, it could even be a trap representation.
    Also, using "sizeof *storage" would be better than "sizeof(double)"
    because if the type ever changes (say, to long double) then you will
    still get the correct amount of space.

    > ptr = &storage[N/2];
    > ...
    > ...
    > ...
    > free(storage);
    >
    >
    > Now ptr points into the middle of the allocated memory area, and I can
    > access elements in the array as ptr[index], where index is a *signed*
    > variable which can take the values -N/2,...N/2. Is this legal
    > behaviour? Or should the index operator only be given unsigned
    > arguments?


    What you are doing is completely legal. You could even do it if you were
    using an array. Obviously, you have to be careful to ensure you don't go
    off the end of the allocated space which can require a little more thought.

    > I have tried using a couple of different compilers on Linux and IRIX,
    > and it seems to work, but it does give me a slightly queasy feeling.


    You are right to ask rather than relying on experimental results, since
    there are "illegal" things that will "work" on some platforms but fail
    on others, one of the classic (IMHO) examples of this being modifying
    string literals.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
    Flash Gordon, Dec 22, 2005
    #3
  4. Joakim Hove

    pete Guest

    Joakim Hove wrote:
    >
    > Hello,
    >
    > I have the following code:
    >
    > #define N 99
    > double *ptr;
    > double *storage;
    > int index;
    >
    > storage = calloc(N , sizeof(double));
    > ptr = &storage[N/2];
    > ...
    > ...
    > ...
    > free(storage);
    >
    > Now ptr points into the middle of the allocated memory area, and I can
    > access elements in the array as ptr[index], where index is a *signed*
    > variable which can take the values -N/2,...N/2. Is this legal
    > behaviour?


    Only if by "Now", you mean before:

    free(storage);

    --
    pete
    pete, Dec 22, 2005
    #4
  5. Joakim Hove

    Eric Sosman Guest

    Joakim Hove wrote:
    > Hello,
    >
    > I have the following code:
    >
    > #define N 99
    > double *ptr;
    > double *storage;
    > int index;
    >
    > storage = calloc(N , sizeof(double));
    > ptr = &storage[N/2];
    > ...
    > ...
    > ...
    > free(storage);
    >
    >
    > Now ptr points into the middle of the allocated memory area, and I can
    > access elements in the array as ptr[index], where index is a *signed*
    > variable which can take the values -N/2,...N/2. Is this legal
    > behaviour? Or should the index operator only be given unsigned
    > arguments?


    Legal, provided N is odd (as shown).

    However, do not be fooled into thinking that "just any"
    offset will work. The above is all right because `ptr' does
    in fact point into the allocated area. The language guarantees
    that `ptr = &storage[k]' will work for all k between 0 and N
    (inclusive at both ends), but not for k outside that range.
    You may occasionally encounter `ptr = &storage[-1]' as part of
    an attempt to imitate the 1-based arrays of Fortran, say, but
    such code is incorrect and need not work at all.

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 22, 2005
    #5
  6. >This is perfectly legal. The array index is treated as a signed integer
    >in C.
    >
    >a is a shorthand way of writing
    >a + sizeof(a)*i


    No, a is a shorthand way of writing *(a + i). It's also equivalent
    to i[a].

    It may also be considered as a shorthand way of writing
    *(a addl (sizeof(a) * i)), where addl is an assembly-language
    addition operator.

    It is allowed for i to be negative provided the storage referred
    to exists.

    Gordon L. Burditt
    Gordon Burditt, Dec 22, 2005
    #6
  7. Joakim Hove

    pete Guest

    Gordon Burditt wrote:
    >
    > >This is perfectly legal. The array index is treated as a signed integer
    > >in C.
    > >
    > >a is a shorthand way of writing
    > >a + sizeof(a)*i

    >
    > No, a is a shorthand way of writing *(a + i). It's also equivalent
    > to i[a].


    Yes.

    > It may also be considered as a shorthand way of writing
    > *(a addl (sizeof(a) * i)), where addl is an assembly-language
    > addition operator.


    I think it should be sizeof(*a), instead of sizeof a.

    --
    pete
    pete, Dec 22, 2005
    #7
  8. Joakim Hove

    Joakim Hove Guest

    Thanks to all of you who answered. It makes my code look much nicer,
    so I am grateful that I can rely on this approach.


    Joakim

    --
    Joakim Hove
    hove AT ntnu.no /
    Tlf: +47 (55 5)8 27 13 / Stabburveien 18
    Fax: +47 (55 5)8 94 40 / N-5231 Paradis
    http://www.ift.uib.no/~hove/ / 55 91 28 18 / 92 68 57 04
    Joakim Hove, Dec 22, 2005
    #8
  9. > No, a is a shorthand way of writing *(a + i). It's also equivalent
    > to i[a].


    Agreed. Pointer arithmatic internally multiples to take care of the
    sizeof.

    --
    EventStudio System Designer 2.5 - http://www.EventHelix.com/EventStudio
    Sequence Diagram Based System Design and Object Modeling Tool
    EventHelix.com, Dec 24, 2005
    #9
    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. prem_eda
    Replies:
    5
    Views:
    7,827
    Pieter Hulshoff
    Oct 11, 2004
  2. dan
    Replies:
    13
    Views:
    528
    Jacek Generowicz
    Sep 17, 2003
  3. Replies:
    11
    Views:
    496
    Antoon Pardon
    Jun 26, 2006
  4. Replies:
    8
    Views:
    1,898
    Csaba
    Feb 18, 2006
  5. Raymond Hettinger
    Replies:
    13
    Views:
    421
    Raymond Hettinger
    Sep 13, 2010
Loading...

Share This Page