473,379 Members | 1,220 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,379 software developers and data experts.

arbitrary array index range?

"A Book on C" explains a technique to use an arbitrary array index range.

int* p = malloc(sizeof(int) * 10) - 1;

This way, the allocated array can be accessed with index range 1 ~ 10,
not 0 ~ 9. You cannot use p[0], of course, and the memory should be
released with free(p + 1).
It worked with gcc and MSVC, but I'm not sure if it makes sense to take
the address before the initial element of an array. Does anyone have
any definite answer?

--
ES Kim
Nov 14 '05 #1
16 3659
"ES Kim" <no@spam.mail> wrote in message news:ck**********@news1.kornet.net...

int* p = malloc(sizeof(int) * 10) - 1;


correction: int* p = (int*)malloc(sizeof(int) * 10) - 1;

--
ES Kim
Nov 14 '05 #2
ES Kim <no@spam.mail> wrote:
"A Book on C" explains a technique to use an arbitrary array index range. int* p = malloc(sizeof(int) * 10) - 1;
Bad book.
This way, the allocated array can be accessed with index range 1 ~ 10,
not 0 ~ 9. You cannot use p[0], of course, and the memory should be
released with free(p + 1).
Whats wrong with indexes starting from zero? I find it the most
natural way ever, since I quit Pascal.

If you really-really need to index from 1, then waste one element:
int* p = malloc(sizeof(int) * (10 + 1));
It worked with gcc and MSVC, but I'm not sure if it makes sense to take
the address before the initial element of an array. Does anyone have
any definite answer?


Pure coincidence. Undefined behaviour.

A pointer can point into an array object or one past the end.

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #3
"ES Kim" <no@spam.mail> wrote:
"ES Kim" <no@spam.mail> wrote in message news:ck**********@news1.kornet.net...

int* p = malloc(sizeof(int) * 10) - 1;


correction: int* p = (int*)malloc(sizeof(int) * 10) - 1;


Not only is the original wrong, so is the correction. You cannot
portably set a pointer to the location before the start of an object.
Both of your lines above could cause segmentation faults, or if you're
less lucky, more unobvious symptoms of undefined behaviour.

Richard
Nov 14 '05 #4
ES Kim wrote:
"ES Kim" <no@spam.mail> wrote in message news:ck**********@news1.kornet.net...
int* p = malloc(sizeof(int) * 10) - 1;

This is invalid and invokes undefined behaviour. Consider what might
happen if the pointer returned by malloc refers to memory which is at
the beginning of a segment for example. The C standard says this is
undefined behaviour because pointer arithmetic on a pointer (in this
case the pointer returned by malloc) must result in a pointer which
points somewhere in the same array or one past the end of that array.

Do not do this. If for some reason you want 1 based arrays just allocate
one extra element and ignore the first one. Usually this is not very
helpful though.


correction: int* p = (int*)malloc(sizeof(int) * 10) - 1;


Err, no.

Recommended malloc usage is something along the lines of

(T is an arbitrary type)

T *ptr = malloc(num_elements * sizeof *ptr);

Notice, no cast and no explicit dependency on the type of ptr
in the argument to malloc. Good Thing!

Search the archives for copious discussion on this.

HTH.

--
Thomas.
Nov 14 '05 #5
On Wed, 13 Oct 2004 23:33:38 +0900
"ES Kim" <no@spam.mail> wrote:
"A Book on C" explains a technique to use an arbitrary array index
range.

int* p = malloc(sizeof(int) * 10) - 1;

This way, the allocated array can be accessed with index range 1 ~ 10,
not 0 ~ 9. You cannot use p[0], of course, and the memory should be
released with free(p + 1).
It worked with gcc and MSVC, but I'm not sure if it makes sense to
take the address before the initial element of an array. Does anyone
have any definite answer?


The only values you are allowed to set a pointer to are:
1) The null pointer
2) Inside a valid C object
3) 1 passed the end of a valid C object.

1 less that the value returned by malloc is none of the above, so doing
that invokes the wrath of undefined behaviour and could cause Russia to
decide to attack you with nuclear missiles. So I would advise against
it.

Also, trying to simulate indexing from a value other than 0 in C
generally causes confusion for other programmers and makes the
introduction of errors. In languages such as Pascal which support
arbitrary indexing it is less likely to cause confusion because people
expect it.

As a final unrelated point, allocation using the form:
type *p = malloc(n * sizeof *p);
is generally less error prone since the type only appears in one place.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #6
Thomas Stegen <th***********@gmail.com> wrote:
ES Kim wrote:
int* p = malloc(sizeof(int) * 10) - 1;
correction: int* p = (int*)malloc(sizeof(int) * 10) - 1;


Err, no.

Recommended malloc usage is something along the lines of


Recommended, but not dogmatic. There are cases where it can
be appropriate to use a cast...

T *ptr = malloc(num_elements * sizeof *ptr);


In this case the cast is necessary, because you cannot do
arithmetic on void pointers (the first example should fail
to compile, or even worse, subtract 1 byte because some
compilers have extensions where void* arithmetic is treated
as char* arithmetic).
Nov 14 '05 #7
In article <84**************************@posting.google.com >,
Old Wolf <ol*****@inspire.net.nz> wrote:
Thomas Stegen <th***********@gmail.com> wrote:
ES Kim wrote:
>
>>int* p = malloc(sizeof(int) * 10) - 1;
>
> correction: int* p = (int*)malloc(sizeof(int) * 10) - 1;
Err, no.

Recommended malloc usage is something along the lines of


Recommended, but not dogmatic. There are cases where it can
be appropriate to use a cast...

T *ptr = malloc(num_elements * sizeof *ptr);


In this case the cast is necessary, because you cannot do
arithmetic on void pointers (the first example should fail
to compile, or even worse, subtract 1 byte because some
compilers have extensions where void* arithmetic is treated
as char* arithmetic).


True, but in this case, it doesn't matter if you invoke undefined behavior
by calling malloc without a prototype (causing the return type to be
incorrectly defaulted to int) and the compiler didn't warn you about
it because you told it to shut up with the cast, because you're already
invoking undefined behavior by creating a pointer off the beginning of
mallocd memory.

The solution is to Just Don't Do That, not to use the cast.
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca I can't think of any programming language whose niche is larger than C's.

English as spoken by teachers in U.S. public schools.
--Dan Pop and Mike Wahler in comp.lang.c
Nov 14 '05 #8
ES Kim wrote:
"A Book on C" explains a technique to use an arbitrary array index range.

int* p = malloc(sizeof(int) * 10) - 1;
int* p = ((int*)malloc(10*sizeof(int))) - 1;
This way, the allocated array can be accessed with index range 1 ~ 10,
not 0 ~ 9. You cannot use p[0], of course,
and the memory should be released with free(p + 1).
It worked with gcc and MSVC,
And it will work with every ANSI/ISO compliant C compiler.
but I'm not sure if it makes sense to take
the address before the initial element of an array.
Does anyone have any definite answer?


According to the ANSI/ISO standards, p is undefined!
Nov 14 '05 #9
E. Robert Tisdale <E.**************@jpl.nasa.gov> wrote:
[snip]
And it will work with every ANSI/ISO compliant C compiler.
[snip]
According to the ANSI/ISO standards, p is undefined!


I envy those people who can write two such sentences together
and still live happily! :-)

--
Stan Tobias
sed 's/[A-Z]//g' to email
Nov 14 '05 #10
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote:
ES Kim wrote:
"A Book on C" explains a technique to use an arbitrary array index range.

int* p = malloc(sizeof(int) * 10) - 1;


int* p = ((int*)malloc(10*sizeof(int))) - 1;


Doesn't help, although in this case the cast is at least conceptually
right. It's the subtraction which is the problem.
This way, the allocated array can be accessed with index range 1 ~ 10,
not 0 ~ 9. You cannot use p[0], of course,
and the memory should be released with free(p + 1).
It worked with gcc and MSVC,


And it will work with every ANSI/ISO compliant C compiler.


Care to explain why something that invokes undefined behaviour would
work with _every_ ISO C compiler?
but I'm not sure if it makes sense to take
the address before the initial element of an array.
Does anyone have any definite answer?


According to the ANSI/ISO standards, p is undefined!


Quite.

Richard
Nov 14 '05 #11
On 13 Oct 2004 16:49:39 -0700, in comp.lang.c , ol*****@inspire.net.nz (Old
Wolf) wrote:
Recommended, but not dogmatic. There are cases where it can
be appropriate to use a cast...
Name one. Answer restricted to C code only.
T *ptr = malloc(num_elements * sizeof *ptr);


In this case the cast is necessary, because you cannot do
arithmetic on void pointers (the first example should fail
to compile,


In the above case if ptr is of type void* then this should just fail to
compile end of story. If ptr is not of type void, then your comment doesn't
seem to make sense.
or even worse, subtract 1 byte because some
compilers have extensions where void* arithmetic is treated
as char* arithmetic)


What?
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 14 '05 #12
Richard Bos wrote:
Care to explain why something that invokes undefined behavior
would work with _every_ ISO C compiler?


The term "undefined behavior" means exactly that.
The ISO C standards do *not* specify the behavior
of pointers to objects outside of array bounds
so they are allowed to "work" and, in fact, they do work
for every compiler that complies with ISO C99.
Nov 14 '05 #13
Mark McIntyre <ma**********@spamcop.net> wrote:
ol*****@inspire.net.nz (Old Wolf) wrote:
In this case the cast is necessary, because you cannot do
arithmetic on void pointers (the first example should fail
to compile,


In the above case if ptr is of type void* then this should just fail to
compile end of story. If ptr is not of type void, then your comment doesn't
seem to make sense.
or even worse, subtract 1 byte because some
compilers have extensions where void* arithmetic is treated
as char* arithmetic)


What?


If we can return to the original case, which seems to have
been misquoted:

malloc(sizeof(int) * 10) - 1
That need not compile on a standards-conforming compiler.
Gcc warns:
g.c:5: warning: pointer of type `void *' used in arithmetic

Furthermore there is a common extension where void* arithmetic
is treated as char* arithmetic. You may not be familiar with
this; the upshot is that the above quote will compile
without warning and give the same result as:

(void *)(((char *)malloc(sizeof(int) * 10)) - 1)

[Note, if you care about the issue that it's undefined
to subtract from the pointer, change all '-' to '+']
Nov 14 '05 #14

In article <oi********************************@4ax.com>, Mark McIntyre <ma**********@spamcop.net> writes:
On 13 Oct 2004 16:49:39 -0700, in comp.lang.c , ol*****@inspire.net.nz (Old
Wolf) wrote:
Recommended, but not dogmatic. There are cases where it can
be appropriate to use a cast...


Name one. Answer restricted to C code only.


Casting an object pointer of another type to unsigned char * in order
to inspect an object's representation, or to copy it to another area
of memory, and so forth. (Note for the second case that we may be
using a freestanding implementation which does not provide memcpy and
memmove.) The alternative is to use an otherwise extraneous temporary
void *. I'd consider the cast in this situation preferable, and so
appropriate.

Casting the result of the sizeof operator to unsigned long in order
to format it with fprintf, in a conforming hosted implementation
prior to C99 (which introduced a conversion specifier guaranteed to
be suitable for size_t).

Casting a plain char or explicitly signed char variable to unsigned
char for use with the is... and to... "functions" defined in ctype.h,
which may be implemented as macros and may invoke UB if called with a
negative value.

I agree that casts should be rare in most well-written C code.

--
Michael Wojcik mi************@microfocus.com

Unlikely predition o' the day:
Eventually, every programmer will have to write a Java or distributed
object program.
-- Orfali and Harkey, _Client / Server Programming with Java and CORBA_
Nov 14 '05 #15
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote:
Richard Bos wrote:
Care to explain why something that invokes undefined behavior
would work with _every_ ISO C compiler?


The term "undefined behavior" means exactly that.
The ISO C standards do *not* specify the behavior
of pointers to objects outside of array bounds
so they are allowed to "work" and, in fact, they do work
for every compiler that complies with ISO C99.


That is so blatant a contradiction that I won't even start trying to
explain where you're going wrong. If you don't see that "It needn't
work, so it works everywhere" is idiotic, there's no curing you.

Richard
Nov 14 '05 #16
On 18 Oct 2004 17:48:14 GMT, in comp.lang.c , mw*****@newsguy.com (Michael
Wojcik) wrote:

In article <oi********************************@4ax.com>, Mark McIntyre <ma**********@spamcop.net> writes:
On 13 Oct 2004 16:49:39 -0700, in comp.lang.c , ol*****@inspire.net.nz (Old
Wolf) wrote:
>Recommended, but not dogmatic. There are cases where it can
>be appropriate to use a cast...


Name one. Answer restricted to C code only.


Casting an object pointer of another type to unsigned char * in order
to inspect an object's representation, or to copy it to another area
of memory, and so forth.


Grin. All accepted.

I was thinking more of the context of Old Wolf's post, which as far as I
recall was suggesting that the casting of malloc was sometimes appropriate.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 14 '05 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Pjotr Wedersteers | last post by:
I have source information in a file, and (part of) this information comes as coordinates. A coordinate consists of a letter followed by a number, ranging from a1 to i9 I'd like to count the...
4
by: PhilC | last post by:
Hi Folks, If I have an array holding a pair of numbers, and that pairing is unique, is there a way that I can find the array index number for that pair? Thanks, PhilC
29
by: shmartonak | last post by:
For maximum portability what should the type of an array index be? Can any integer type be used safely? Or should I only use an unsigned type? Or what? If I'm using pointers to access array...
8
by: Joe Rattz | last post by:
Ok, I can't believe what I am seeing. I am sure I do this other places with no problems, but I sure can't here. I have some code that is indexing into the ItemArray in a DataSet's DataRow. I...
26
by: Szabolcs Nagy | last post by:
what type can/should be used as array index? eg. can i use unsigned long? or should it be size_t? example: int sum(int *a, index_t n) { int s = 0; index_t i;
1
by: Sippeangelo | last post by:
Well I have a string with a couple of words. "Blah hello smart" They get divided up into an array like so: = "Blah" = "hello" = "smart" Now if the string is only "Blah" I only get one...
4
by: BravoFoxtrot | last post by:
Hi, I'm trying to build an index into a multi dimensional associative array. I may not know how many dimensions there are so i want to pass the array indexes as a variable. $arrayToAccess =...
1
by: rahulkhunteta | last post by:
Request object error ‘ASP 0105 : 80004005’ Index out of range /printcdsc/printsubscriptionsmainpage.asp,line55 An array index is out of range. I am getting this message while submitting a...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.