Negative indices to a vector: Valid?

J

Joakim Hove

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
 
E

EventHelix.com

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].
 
F

Flash Gordon

Joakim said:
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.
 
P

pete

Joakim said:
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);
 
E

Eric Sosman

Joakim said:
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.
 
G

Gordon Burditt

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
 
P

pete

Gordon said:
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.
 
J

Joakim Hove

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
 
E

EventHelix.com

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

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

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top