But they had their way, and it doesn't.
- Greg
--
Comeau Computing, Producers of Comeau C/C++ 4.2.42 (4.2.43 BETA starting)
Try Comeau C++ online at http://www.comeaucomputing.com/tryitout
Email: com...@comeaucomputing.com / WEB: http://www.comeaucomputing.com
>When dimensioning an array with 10 elements you get an index system
>starting at 0 and ending with 9... In some cases it is better (more
>convienent) to have the index start at 1 and end at 10... In BASIC
>there is a method called OPTION BASE = 1 that makes the array index
>start at 1... Is there a method of doing this in c/c++...??? I
>basically want the first element in the array to start at 1 instead of
>the usual 0.....
int i_[ 10 ] ;
int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
Br,
Andras Erdei
Andras Erdei
c...@freemail.hu
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
>int i_[ 10 ] ;
>int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
Please, not again.
The omputation of i_ - 1 has undefined effect, because you're
not allowed to compute an address that's off the beginning of
an array (or that's more than one element off the end).
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
I've seen this before, and IIRC it's incorrect.
True, it's close, and likely to work. But the main reason it often
works is that it's easier for the compiler vendor get right.
The problem is that only adresses i_ up to and including i_+10 are
valid adresses. i_+10 is a valid address, but it doesn't point to data.
This means you don't have to worry that calculating i_+10 might overflow
your pointer or do other nasty things.
OTOH, it's perfectly valid for a compiler to allocate i_ at address 0x0001.
It may also test for pointer arithmetic on NULL pointers, and use 0x0000 as
a NULL pointer. You'd create a pointer with value i=0x0000, try to add an
index (1..10) to a NULL pointer, and fail.
In short, you can only create pointers to NULL, to objects or directly after
arrays. In your example 'i' isn't assignedone of those.
Michiel Salters
Undefined behaviour.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
encapsulate your array in a class, and write your own operator[]
Something like:
template <class T, const int Size, const int Base> class based_array
{
private:
T *data;
public:
based_array() { data = new T[Size]; };
~based_array() { delete[] data; };
T& operator[](const int i) { return data[i-Base];};
Not particularly, but it was type of logic I applied in my response
as well: The each respectively controlled their languages for
many years, and if they felt so stong as Tisdale is saying they
do about this point, then then would have changed it. But they didn't
change it, so then it seem that they didn't feel that way.
Somehow I suspect some point is out of context here, because
this thread is just not following...
No.
They had complete control of their respective language for many
years before the standardization process began. Seems like
that was enough time to fix _this issue_ if they felt so
strongly opinionated on it, hence this leads me to believe that
one or more of the following seems to be the case:
1) You're wrong.
2) You're not stating your point well
3) I'm not understanding your point for some reason
All of this is independent of that during standardization people
disagreed with them on certain points.
If you have some specific quote from them to back up what you're
saying, then present it. Otherwise, I feel this will be circular.
BTW, personally I don't care for every aspect of pointer/array
interaction, or lack thereof, but that's a seperate issue from
what the respective standard says, and following it. Too, I have
often voted for something on that I would have voted contrary
to on a personal level (for instance, something in isolation
may be great, but when considered within the whoe standard, isn't).
I'm sure other committee member has voted similarly (or if not
voted, then acted so).
When dimensioning an array with 10 elements you get an index system starting at 0 and ending with 9... In some cases it is better (more convienent) to have the index start at 1 and end at 10... In BASIC there is a method called OPTION BASE = 1 that makes the array index start at 1... Is there a method of doing this in c/c++...??? I basically want the first element in the array to start at 1 instead of the usual 0..... Thanks in advance for any information....!!!!*s*
Sincerely,
-- Trevor Penney, A+, Network+
I'm a compiler developer and don't believe so, nor do any
other the other compiler developers that I know believe they are,
so your hunch is wrong in this case.
>Different interpretations of the standards documents
>are usually only apparent when compilers emit code
>that behaves differently for the same source program.
>If all the programs behave the same way,
>different interpretations are never tested.
>Eventually, so many source programs will be written,
>compiled and tested with compilers that emit code
>which behaves in a certain way that it is impossible
>to "correct" any compiler so that it is "consistent"
>with any particular interpretation of the standards documents.
Like I said, you're overstating this. Such situations should
be the exception not the rule.
> In article <n7qhis420cmc1l110...@4ax.com>,
> Andras Erdei <c...@freemail.c3.hu> wrote:
>
> > int i_[ 10 ] ;
> > int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
>
> Please, not again.
>
> The computation of i_ - 1 has undefined effect,
> because you're not allowed to compute an address
> that's off the beginning of an array
> (or that's more than one element off the end).
Nonsense!
It will work almost everywhere.
Yes you would have some wraparound with array-1, but when used with any
index >=1, the same wraparound would occur and you would get the correct
address.
- Matthias Meixner
--
Matthias Meixner mei...@rbg.informatik.tu-darmstadt.de
Technische Universität Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstraße 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
"E. Robert Tisdale" wrote:
>
> Andrew Koenig wrote:
>
> > In article <n7qhis420cmc1l110...@4ax.com>,
> > Andras Erdei <c...@freemail.c3.hu> wrote:
> >
> > > int i_[ 10 ] ;
> > > int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
> >
> > Please, not again.
> >
> > The computation of i_ - 1 has undefined effect,
> > because you're not allowed to compute an address
> > that's off the beginning of an array
> > (or that's more than one element off the end).
>
> Nonsense!
The only nonsense here is yours.
> It will work almost everywhere.
What evidence do you have of this fact? I have a machine at home that
has a C compiler. Without knowing what machine it is, can you guarantee
that the above code will work as you expect on it? If not, then your
assertion is valueless, because nobody can guarantee what machine their
code will end up being compiled on. And if you /can/ guarantee that your
code will work on my machine, I'd be fascinated to know how you arrive
at such a guarantee, and whether you'd be prepared to stake your
reputation on that guarantee.
The ISO/ANSI C specification is quite clear - this code invokes
undefined behaviour.
--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
37 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (60
to go)
>Andrew Koenig wrote:
>
>> In article <n7qhis420cmc1l110...@4ax.com>,
>> Andras Erdei <c...@freemail.c3.hu> wrote:
>>
>> > int i_[ 10 ] ;
>> > int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
>>
>> Please, not again.
>>
>> The computation of i_ - 1 has undefined effect,
>> because you're not allowed to compute an address
>> that's off the beginning of an array
>> (or that's more than one element off the end).
>
>Nonsense!
It seemed very sensical to me.
>It will work almost everywhere.
Andrew didn't say "It won't work." He said that it had an undefined
effect, and thus may do absolutely anything -- including what you
expected.
Are you endorsing deliberate ignorance of the standards? Do you
*really* want to go off into undefined behaviour land when there is a
perfectly good alternative? Or are you just being difficult?
--
Chris Mears
ICQ: 36697123
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
The only case I have seen, that compilers test for NULL-pointers is when converting
objects from a class to base class or vice versa, since it needs to recalculate
the beginning of the object in case of multiple inheritance. Since this does not
work with arrays anyway, it is of no interest in this case.
Although dereferencing the NULL-pointer is undefined behaviour, as soon as you
dereference it using an index which is != 0, it is no NULL-pointer any more:
Lets assume i_==0x1 and i==0
i[1] is equivalent to *(i+1) which dereferences the pointer to 1, which is
perfectly legal.
BTW: Even dereferencing the NULL pointer is commonly used (from stddef.h of gcc):
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
- Matthias Meixner
--
Matthias Meixner mei...@rbg.informatik.tu-darmstadt.de
Technische Universität Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstraße 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
>> The computation of i_ - 1 has undefined effect,
>> because you're not allowed to compute an address
>> that's off the beginning of an array
>> (or that's more than one element off the end).
>Nonsense!
>It will work almost everywhere.
Please remember that `almost' is nothing more than
a polite way of saying `not.'
In other words, it will not work everywhere.
I have certainly encountered implementations on which it will not work.
There is no requirement on any implementation to make it work.
Even if it happens to work on a particular implementation, there
is no requirement for it to continue to work in future releases.
Anyone who wants to rely on such behavior is taking needless risks.
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
Note that it does not matter whether compilers actually do use the fact
that a user is not allowed to dereference a null pointer or not. What
matters is that a compiler is allowed to generate code resulting in
whatever it likes to do if a user actually dereference a null pointer!
Althought dereferencing a null pointer might work on basically all
implementations you are testing it, it might not work on some system.
The language makes certain guarantees and certain assumptions. If you
violate these assumptions, eg. that you are only dereferencing a valid
pointer and eg. not a null pointer, there are no guarantees. Thus, you
should only dereference valid pointers.
: Although dereferencing the NULL-pointer is undefined behaviour, as soon
as you
: dereference it using an index which is != 0, it is no NULL-pointer any
more:
Can you please point me at the section allowing this in either the C or
the
C++ standard? Hint: There is no such section!
: Lets assume i_==0x1 and i==0
: i[1] is equivalent to *(i+1) which dereferences the pointer to 1,
which is
: perfectly legal.
This code is plain illegal. Please quote the section allowing it. BTW,
saying that all compilers you have tested it on allow this is different
from a guarantee by the standard: There are definitely compilers around
which disallow such use and even those currently allowing it might change
in the next version to forbid it.
: BTW: Even dereferencing the NULL pointer is commonly used (from
stddef.h of gcc):
: #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Note that <stddef.h> is part of the implementation which can make
assumption beyond the guarantees provided by the standard because it is
intimately familiar with the compiler implementation. This does not
make the code portable, though.
--
<mailto:dietma...@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly
pessimistic
When you read the C standard you will find that adding something to the
NULL
pointer yields undefined behaviour.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland,
+31205924131
home: bovenover 215, 1025 jn amsterdam, nederland;
http://www.cwi.nl/~dik/
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
: > In article <n7qhis420cmc1l110...@4ax.com>,
: > Andras Erdei <c...@freemail.c3.hu> wrote:
: >
: > > int i_[ 10 ] ;
: > > int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
: >
: > Please, not again.
: >
: > The computation of i_ - 1 has undefined effect,
: > because you're not allowed to compute an address
: > that's off the beginning of an array
: > (or that's more than one element off the end).
: Nonsense!
: It will work almost everywhere.
^^^^^^
I think it is funny how you are contradicting your statement that what
Andy said is nonsense: You are right, it will work *almost* everywhere.
The important point is, however, that you cannot rely on it to work
because you might be at one of the places where it does not work.
However, there are approaches which do work everywhere and I think they
are superior just because they work reliable.
--
<mailto:dietma...@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly
pessimistic
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
> On 23 May 2000 00:15:19 -0400,
> E. Robert Tisdale wrote:
>
> > Andrew Koenig wrote:
> >
> > > In article <n7qhis420cmc1l110...@4ax.com>,
> > > Andras Erdei <c...@freemail.c3.hu> wrote:
> > >
> > > > int i_[ 10 ] ;
> > > > int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
> > >
> > > Please, not again.
> > >
> > > The computation of i_ - 1 has undefined effect,
> > > because you're not allowed to compute an address
> > > that's off the beginning of an array
> > > (or that's more than one element off the end).
> >
> > Nonsense!
>
> It seemed very sensical to me.
>
> > It will work almost everywhere.
>
> Andrew didn't say "It won't work."
> He said that it had an undefined effect,
> and thus may do absolutely anything --
> including what you expected.
Andrew said, "you're not allowed to compute an address
that's off the beginning of an array".
That's nonsense.
You can, indeed, compute an address
that's off the beginning of an array
and every C and C++ compiler will allow you to do it.
The standards documents simply don't specify
any meaningful result for such a calculation.
> Are you endorsing deliberate ignorance of the standards?
> Do you *really* want to go off into undefined behavior land
> when there is a perfectly good alternative?
> Or are you just being difficult?
No.
You're the one who is ignoring the standards.
You think that the standards documents are the standards.
They are not. They are only one component of the standards.
They are a formal articulation of the standards.
You must also consider expert interpretation of the standards,
actual implementations of compilers
and how the languages are actually used in practice.
You wrote:
> There's no standard way of doing this.
> A terribly non-portable way would be
> to take the address of the element before the first,
> and index from that. e.g.:
>
> void f(void) {
> int array[10];
> int *ptr = array - 1;
> ptr[1] = 1;
> ptr[10] = 10;
> /* Cannot use ptr[0]. */
> }
>
> However, this is definitely not portable.
But it is, in fact, way portable.
The standards documents may indicate
that the behavior is undefined
but that has no practical meaning
to most compiler developers
because trick is used in thousands of existing
C and C++ programs.
They might implement a C or C++ compiler
which would refuse to accept your example
or emit code which did something unexpected
but nobody would buy or use their compiler.
On the other hand, C compiler developers
for a tiny new embedded processor
using saturating integral arithmetic
may decide not to support "out-of-bounds"
address calculations because it is too expensive
to support wrap around integral arithmetic.
They don't really expect anyone to port
legacy code to the new platform so they don't care
if programs like your example break.
They would probably prefer that
the standards documents did not specify
the behavior for your address calculation.
I told you that
this was actually a very subtle question.
Perhaps now you are beginning to believe me.
Sure, programmers' lives would be much simpler
if there was a single document
which they could reference
to tell them how to write really good portable code
but no standards document will serve this purpose.
> When dimensioning an array with 10 elements you get an index system
> starting at 0 and ending with 9... In some cases it is better (more
> convienent) to have the index start at 1 and end at 10...
It very rarely is. Indexing from 0 makes sense, as 0 is the first
(unsigned) integer.
> In BASIC
> there is a method called OPTION BASE = 1 that makes the array index
> start at 1... Is there a method of doing this in c/c++...???
No. Indexing from 0 is fundamental in C, because array operations an
boil down to pointer arithmetic. Learn to program in C, not with BASIC
in C.
--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ If you are afraid of loneliness, do not marry.
\__/ Anton Chekhov
Interstelen / http://www.interstelen.com/
A multiplayer, strategic, turn-based Web game on an interstellar scale.
--
comp.lang.c.moderated - moderation address: cl...@plethora.net
By the way, if you post in HTML again, I'm going to have to poleaxe you.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. Newsgroup http://www.dejanews.com/~c_a_p
C.A.P. FAQ: ftp://38.168.214.175/pub/Chess%20Analysis%20Project%20FAQ.htm
No, but you can (a) define a macro that would make a shift, or (b) [C++
only] wrap your array in a class that will provide the index
translation.
Victor
--
Please remove capital A's from my address when replying by mail
#1 - c/c++ is not a language. They're two very different languages. You
may be able to do something with operator overloading in C++. I don't
know, though.
#2 - please don't post in HTML. Peter - does clcm have a policy about
HTML posts?
[yes. if my mail reader doesn't filter them out for me before I notice them,
I bounce them. I eventually plan to patch the posting script to always
bounce them as "binaries". -mod]
#3 - There is a way, kind of. If you really want to do this you could
do something like:
static char* zeroBased = "Hello, world";
static char* oneBased = zeroBased - 1;
Now oneBased[1] == 'H'
and oneBased[2] == 'e'
But you probably don't really want to do this. The index that arrays
start at is really just a convention of the language. Breaking the
conventions of the language will simply serve to make interactions with
other libraries more difficult and to complicate the lives of other
programmers who need to read and maintain your code.
/peter
} When dimensioning an array with 10 elements you get an index system
} starting at 0 and ending with 9... In some cases it is better (more
} convienent) to have the index start at 1 and end at 10... In BASIC
} there is a method called OPTION BASE = 1 that makes the array index
} start at 1... Is there a method of doing this in c/c++...??? I
} basically want the first element in the array to start at 1 instead of
} the usual 0..... Thanks in advance for any information....!!!!*s*
I think this might be in the FAQ (I don't have it in front of me, but I
don't know), but you could use a macro of this sort:
#define ELEMENT(arr,n) (arr)[(n) - 1]
Or other such non-sense. Of course, you could simply allocate one more
element than you need and disreguard the element at 0...
--
|| Bill Wendling wend...@ncsa.uiuc.edu
|| Coding Monkey
Please, let us know in what cases counting 1 - 10 is better.
Dirk
> In article <3929393B...@netwood.net>,
> E. Robert Tisdale <ed...@netwood.net> wrote:
> >Andrew Koenig wrote:
>
> >> The computation of i_ - 1 has undefined effect,
> >> because you're not allowed to compute an address
> >> that's off the beginning of an array
> >> (or that's more than one element off the end).
>
> >Nonsense!
>
> >It will work almost everywhere.
>
> Please remember that `almost' is nothing more than
> a polite way of saying `not.'
>
> In other words, it will not work everywhere.
>
> I have certainly encountered implementations on which it will not work.
>
> There is no requirement on any implementation to make it work.
>
> Even if it happens to work on a particular implementation, there
> is no requirement for it to continue to work in future releases.
>
> Anyone who wants to rely on such behavior is taking needless risks.
As an example:
static int a [10];
int f (int* p) { a [9] = 42; p [10] = 0; return a [9]; }
void g (void) { int result = f (a - 1); assert (result == 0); }
It looks like the call to f () would set a [9] = 42, a [9] = 0, return 0.
However, since obviously an assignment to p [10] cannot possibly change
any element of the array a without undefined behavior, an optimising
compiler can safely assume that the assignment to p [10] cannot change a
[9], and function f returns the value 42.
In C++: I guess there is. You can redefine the [] notation to mean
whatever you want, if you need it. I'ld advise strongly against doing
that, though. You'ld be making you program extremely easy to misread
by other, more native C++ programmers.
In C: no. At least one well-known book on numerical algorithms claims
there is, but they're plain wrong: their method evokes undefined
behaviour, which by definition of the term is the worst kind of error
a C program can possibly have.
--
Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
> In article <3928AA4B...@netwood.net>
> "E. Robert Tisdale" <ed...@netwood.net> writes:
>
> > I have a hunch that all compiler developers believe
> > that they are conforming to the standards documents.
>
> I'm a compiler developer and don't believe so,
> nor do any of the other compiler developers that I know
> believe they are, so your hunch is wrong in this case.
> > Different interpretations of the standards documents
> > are usually only apparent when compilers emit code
> > that behaves differently for the same source program.
> > If all the programs behave the same way,
> > different interpretations are never tested.
> > Eventually, so many source programs will be written,
> > compiled and tested with compilers that emit code
> > which behaves in a certain way that it is impossible
> > to "correct" any compiler so that it is "consistent"
> > with any particular interpretation of the standards documents.
> Like I said, you're overstating this.
> Such situations should be the exception not the rule.
That's wishful thinking Greg.
> No.
> They had complete control of their respective language
> for many years before the standardization process began.
> Seems like that was enough time to fix _this issue_
> if they felt so strongly opinionated on it,
I can't even think of a reason why they would even need to
address _this issue_ before the standardization process began.
> This leads me to believe that
> one or more of the following seems to be the case:
> 1) You're wrong.
> 2) You're not stating your point well.
> 3) I'm not understanding your point for some reason.
Maybe. But I don't think so.
My opinion is based upon published remarks
made by the C and C++ language designers.
I might try to collect them all together some day
but it would probably be better
if they addressed the issue directly themselves
instead of relying on my (or anyone else's)
interpretation of their remarks.
> My opinion is based upon published remarks
> made by the C and C++ language designers.
So cite one of these opinions. Put up or shut up.
Be patient.
I'm working on a little essay but it will take a while.
Look for a new thread about arrays, subscripts, etc.
some time in the next few weeks.
No thanks, we've had enough.
dave
--
Dave Vandervies dj3v...@student.math.uwaterloo.ca
There are two kinds of fools -- those who never climb Mt. Fuji, and those who
climb it twice. -- Old Japanese proverb (according to the BSD fortune file)
Definitely, there should be no debate about that. I'd suggest to the
original poster - if you really want off-by-one indexing, just
allocate one extra element and don't use the zeroth element.
Andrei
>> Andrew didn't say "It won't work."
>> He said that it had an undefined effect,
>> and thus may do absolutely anything --
>> including what you expected.
>Andrew said, "you're not allowed to compute an address
>that's off the beginning of an array".
>That's nonsense.
>You can, indeed, compute an address
>that's off the beginning of an array
>and every C and C++ compiler will allow you to do it.
Not every C and C++ compiler will allow you to do it.
When I say "you're not allowed to compute an address that's off
the beginning of an array," that is an abbreviation for
"If you compute an address that's off the beginning of an array,
the implementation is entitled to do anything it pleases."
>You think that the standards documents are the standards.
>They are not. They are only one component of the standards.
>They are a formal articulation of the standards.
>You must also consider expert interpretation of the standards,
>actual implementations of compilers
>and how the languages are actually used in practice.
Yes you must consider those things, but they are not standards.
>> However, this is definitely not portable.
>But it is, in fact, way portable.
No it isn't. I have seen compilers that reject it.
>The standards documents may indicate
>that the behavior is undefined
>but that has no practical meaning
>to most compiler developers
>because trick is used in thousands of existing
>C and C++ programs.
Perhaps so, but it's still not portable.
>They might implement a C or C++ compiler
>which would refuse to accept your example
>or emit code which did something unexpected
>but nobody would buy or use their compiler.
False. Such a compiler exists, and people have bought it.
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
There are probably dozens of additional people who panned him (such as me).
And many others who knew the lunacy of the stand but did not deem entering
the fray worth the bother. I don't think that Richard promised an
exhaustive list of dissenters. Actually, it would be a pretty simple
calculation:
dissenters = readership_of_clc + readership_of_clcpp - e_r_tisdale * w;
But the -1 {value of e_r_tisdale} is actually a weighted value, having a
weight calculated by inverting a hyper-real.
That makes the true end number of dissenters a bit more difficult to
calculate precisely, since it involves infinitesimals. Maybe we should try
Maple.
>Hey guys,
>
>When dimensioning an array with 10 elements you get an index system
>starting at 0 and ending with 9...
hi, you've posted this repeatedly for days now. Are you actually
reading the responses?
>In some cases it is better (more
>convienent) to have the index start at 1 and end at 10...
Show me one. I can't think of any offhand.
>In BASIC
>there is a method called OPTION BASE = 1 that makes the array index
>start at 1...
Hardly a good example. A language that LETS you introduce gratuitous
confusiuon...
>Is there a method of doing this in c/c++...???
No.
>I basically want the first element in the array to start at 1 instead of
>the usual 0.....
Thats a silly idea. It will simply confuse all your colleagues, simply
because you are unable to perform the necessary mind-shift. You would
be in a very small minority of C programmers.
--
Mark McIntyre
C- FAQ: http://www.eskimo.com/~scs/C-faq/top.html
> Chris Mears wrote:
>
> > The method I provided *might* work on your compiler,
> > but you I can't guarantee it.
> > The compiler's documentation might mention something about it.
> > Don't use that code if you want 100% reliability.
>
> In fact, it will work almost everywhere. And, I believe that
> if Brian W. Kernighan, Dennis M. Ritchie and Bjarne Stroustrup
> had their way the standards documents would clearly state
> that it should work everywhere.
I don't think so. As far as I know, no C or C++ manual or standard has ever
allowed access beyond the beginning of an array or even allowed forming a
pointer to there. Nor have I ever heard Dennis or Brian argue for such to be
allowed.
You can use negative indices, but only as long as the resulting pointer
refers to an element of the array that the pointer you index off, or one
beyond the end. For example:
int v[100];
int* p = &v[50];
void f()
{
int a = p[-20]; // ok
int b = p[-200]; // error
// ...
}
An ordinary compiler would not catch the error except possibly in trivial
cases like my example.
The reason to disallow such pointers is that an array, such as v here,
might be allocated on or near a hardware boundary so that there logically
and physically isn't an element to refer to. Hardware might give some
hardware error when the address is formed in a register or used for access,
or truncate the pointer that is former for p[-200] so that it refers to
some other memory (probably beyond the other end of the array).
> With your permission,
> I will refer to Bjarne Stroustrup as Him from now on.
Please don't.
- Bjarne
Bjarne Stroustrup - http://www.research.att.com/~bs
> "E. Robert Tisdale" <ed...@netwood.net> writes:
>
> > Chris Mears wrote:
> >
> > > The method I provided *might* work on your compiler,
> > > but you I can't guarantee it.
> > > The compiler's documentation might mention something about it.
> > > Don't use that code if you want 100% reliability.
> >
> > In fact, it will work almost everywhere. And, I believe that
> > if Brian W. Kernighan, Dennis M. Ritchie and Bjarne Stroustrup
> > had their way the standards documents would clearly state
> > that it should work everywhere.
>
> I don't think so.
> As far as I know, no C or C++ manual or standard has ever allowed
> access beyond the beginning of an array
> or even allowed forming a pointer to there.
> Nor have I ever heard Dennis or Brian argue for such to be allowed.
>
> You can use negative indices, but only as long as the resulting pointer
> refers to an element of the array that the pointer you index off,
> or one beyond the end. For example:
>
> int v[100];
> int* p = &v[50];
>
> void f(void) {
> int a = p[-20]; // ok
> int b = p[-200]; // error
> // ...
> }
>
> An ordinary compiler would not catch the error
> except possibly in trivial cases like my example.
>
> The reason to disallow such pointers is that an array, such as v here,
> might be allocated on or near a hardware boundary
> so that there logically and physically isn't an element to refer to.
> Hardware might give some hardware error
> when the address is formed in a register or used for access,
> or truncate the pointer that is former for p[-200]
> so that it refers to some other memory
> (probably beyond the other end of the array).
> > With your permission,
> > I will refer to Bjarne Stroustrup as Him from now on.
> Please don't.
Thanks Bjarne,
And please forgive my troll.
But there are too few carefully chosen words said
about arrays and pointer arithmetic.
The topic really deserves a more thorough treatment
especially in regards to numerical computing.
I'm sure that you are well aware that
the trick which Chris Mears describes is common
in numerical computing and used extensively
in "Numerical Recipes in C" for example.
I don't see any reason why you, Dennis or Brian
would need to specify this in any manual
or standards document but I don't think
any compiler developer is going to break
all of the existing code which relies on this trick
if they don't need to do so. Do you?
I would argue that it is a de facto standard
and there is nothing that you, Dennis or Brian
could or should do about it.
Mr Tisdale says that Mr Stroustrup's view is that foo[-1] is defined,
and that if only people listened to Mr Stroustrup, all would be well...
> >
> > I don't think so.
> > As far as I know, no C or C++ manual or standard has ever allowed
> > access beyond the beginning of an array
> > or even allowed forming a pointer to there.
> > Nor have I ever heard Dennis or Brian argue for such to be allowed.
Mr Stroustrup disagrees with Mr Tisdale...
<snip>
> I would argue that it is a de facto standard
> and there is nothing that you, Dennis or Brian
> could or should do about it.
Mr Tisdale is suddenly less keen to accept the opinions of the C and C++
demigods.
E. Robert, you're going round in circles. I think you're wrong. But what
does my opinion matter?
Let's see. Kaz thinks you're wrong. Martin Ambuhl thinks you're wrong.
Ben Pfaff thinks you're wrong. Greg Comeau thinks you're wrong. Dik
Winter thinks you're wrong. Even Bjarne Stroustrup thinks you're wrong.
Has it ever occurred to you that the reason all these highly clueful
people think you're wrong might just be, for once, possibly, that you
might be - er - wr... wro... wr... wrwrwrwrwr... (ahem) not right?
--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
37 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (60
to go)
You forgot me! I think he's wrong too!
>Has it ever occurred to you that the reason all these highly clueful
>people think you're wrong
...or is it just that I'm not clueful enough to attain the rank of
`highly clueful'?
> might just be, for once, possibly, that you
>might be - er - wr... wro... wr... wrwrwrwrwr... (ahem) not right?
Just curious, you see... (Or is it that I only spoke up once or twice
and then got tired of the argument?)
dave
--
Dave Vandervies dj3v...@student.math.uwaterloo.ca
[-hs-]>>target) do a websearch. Try www.goggle.com A good engine.
[Dave]>I think you mean www.google.com .
[-hs-]Oh yes, a godd engine ! - -hs- being corrected in comp.lang.c
Let's see it from a more practical point of view.
This method is most probably one of the most efficient ways of shifting the
index (if you want another reagion, e.g. 100000..100010 simply allocating
some more memory is not really an option), since it does not slow down
the speed of the actual access to an array element, whereas wrapping
it with a class or whatever, that corrects the index at any access does
(unless you have got a compiler with really fancy optimizations).
So if you write code, that is not portable anyway, since it is e.g. for
Windows or Linux or ... , then simply forget about portability, since
this construct is much more portable, than the rest of the code.
IMHO, if you start to use some more specialized includes and/or library-functions,
your code starts not being portable. If you rely on minimal sizes of some
types (e.g. int) your code won't be portable too (AFAIR int may have even as few
as 8 bits or even less).
So take the simple loop:
int i;
for(i=0;i<1000;i++) {....}
Is this portable? No, it will break on systems on which an int has only 9 bit.
Guess why quite some code is messed up with things like "#ifdef solaris",
"#ifdef linux" and so on.
So I see it as a trade off between simplicity of the sourcecode (and in many
cases speed of the program) versus portability. So look at your program or
part of code that should be reused and look which part of it is the
least portable section. Then estimate, how much work it would be to make
it portable and if it would be worth it. If not simply forget about
portability for the rest.
- Matthias Meixner
--
Matthias Meixner mei...@rbg.informatik.tu-darmstadt.de
Technische Universität Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstraße 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
> Just out of curiosity -- under what circumstances would starting the
> index at 1 instead of 0 be more convenient?
Suppose you are implementing an array representation of a binary tree.
This happens when implementing a heap representation of a priority queue.
Then you will have:
parent(x) = x / 2
left_child(x) = x * 2
right_child(x) = left_child(x) + 1 = (x * 2) + 1
So an example tree might be:
1
2 3
4 5 6 7
(#'s represent array index for the node).
If you start at 0, this doesn't work.
0
1 2
3 4 5 6
0 * 2 = 0, yet the root node can't have itself for a left-child. Also,
node at index 2 would be root's right child. 2 / 2 = 1, but that is node
2's *sibling*, not its parent (the root). In a nutshell, the tree is a
screwed up mess.
But if we start numbering the nodes at index 1, the math works just fine.
I find it's best to just not use the first array element in a situation
like this. This is the _only_ occasion where I've found that starting at
1 made sense. Starting at 0 is generally nicer because:
&x[i] = x + i
-Adam
Adam McKee wrote:
>
>
> parent(x) = x / 2
> left_child(x) = x * 2
> right_child(x) = left_child(x) + 1 = (x * 2) + 1
>
> So an example tree might be:
>
> 1
> 2 3
> 4 5 6 7
>
> (#'s represent array index for the node).
>
> If you start at 0, this doesn't work.
>
> 0
> 1 2
> 3 4 5 6
>
Sure, because the expressions for parent, left_child, right_child
are designed to work with "1 indexing"
But if you change them, you can make them work with "0 indexing"
too
parent(x) = ( x / 2 ) - 1
left_child(x) = ( x * 2 ) + 1
right_child(x) = left_child(x) + 1 = ( x * 2 ) + 2
0
1 2
3 4 5 6
Agreed: The expressions get a little bit more complicated then
in the "1 index" case. But there are other cases, where the
opposite is true.
-----------------------------------------------------------
Karl Heinz Buchegger
kbuc...@gascad.at
Probably. Let's say it's about 95% portable. I still like 100%
portable more. :)
>IMHO, if you start to use some more specialized includes and/or library-functions,
>your code starts not being portable. If you rely on minimal sizes of some
>types (e.g. int) your code won't be portable too (AFAIR int may have even as few
>as 8 bits or even less).
int has at least 16 bits on all comforming implementations.
>So take the simple loop:
>
>int i;
>for(i=0;i<1000;i++) {....}
>
>Is this portable?
Yes, except for the syntax error inside the curly braces.
>No, it will break on systems on which an int has only 9 bit.
The range for int is guaranteed to be at least -32767 to +32767
>Guess why quite some code is messed up with things like "#ifdef solaris",
>"#ifdef linux" and so on.
>
>So I see it as a trade off between simplicity of the sourcecode (and in many
>cases speed of the program) versus portability. So look at your program or
>part of code that should be reused and look which part of it is the
>least portable section. Then estimate, how much work it would be to make
>it portable and if it would be worth it. If not simply forget about
>portability for the rest.
I find it easier to separate the program into portability-ness. If I
can write some of the modules portably, I do so. The system-specific
stuff like graphics or hardware can be shoved off somewhere else, so
that if I ever port the program I can rip out the non-portable stuff
and replace it without maiming the rest of the code.
--
Chris Mears
ICQ: 36697123
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<snip a whole bunch>
> There are probably dozens of additional people who panned him (such as
> me). And many others who knew the lunacy of the stand but did not deem
> entering the fray worth the bother.
...or others, like myself, who simply had the decency to make their
killfile grow by one entry. (I can take one or two replies but to be so
relentlessly stubborn about something in black in white is too much for
even Mother Teresa to bear.)
Cheers,
Selim
--
"Although personally I am quite content with existing explosives, I feel
we must not stand in the way of improvement."
- Sir Winston Churchill, from "The Second World War" in reference to the
possibility of making a nuclear bomb
> In article <392A9FC0...@netwood.net>,
> E. Robert Tisdale <ed...@netwood.net> wrote:
>
> > > Andrew didn't say "It won't work."
> > > He said that it had an undefined effect,
> > > and thus may do absolutely anything --
> > > including what you expected.
>
> > Andrew said, "you're not allowed to compute an address
> > that's off the beginning of an array".
> > That's nonsense.
> > You can, indeed, compute an address
> > that's off the beginning of an array
> > and every C and C++ compiler will allow you to do it.
>
> Not every C and C++ compiler will allow you to do it.
Which ones?
> When I say "you're not allowed to compute an address that's off
> the beginning of an array," that is an abbreviation for
> "If you compute an address that's off the beginning of an array,
> the implementation is entitled to do anything it pleases."
>
> > You think that the standards documents are the standards.
> > They are not. They are only one component of the standards.
> > They are a formal articulation of the standards.
> > You must also consider expert interpretation of the standards,
> > actual implementations of compilers
> > and how the languages are actually used in practice.
>
> Yes you must consider those things, but they are not standards.
>
> > > However, this is definitely not portable.
>
> > But it is, in fact, way portable.
>
> No it isn't. I have seen compilers that reject it.
Which ones?
> > The standards documents may indicate
> > that the behavior is undefined
> > but that has no practical meaning
> > to most compiler developers
> > because trick is used in thousands of existing
> > C and C++ programs.
>
> Perhaps so, but it's still not portable.
Which compiler won't accept it?
> > They might implement a C or C++ compiler
> > which would refuse to accept your example
> > or emit code which did something unexpected
> > but nobody would buy or use their compiler.
>
> False. Such a compiler exists, and people have bought it.
Which compiler are you talking about?
You are making a category error.
The results of dereferencing a null pointer in user code are undefined.
The offsetof macro is part of the implementation, and is not user code.
The implementation need not be written using portable, or even
standard-conforming, code, since it needs only to be self-consistent.
Presumably, the gcc implementation is such that the above macro
produces good results. The code might not (and need not) work on any
other system.
--
Steve Clamage, stephen...@sun.com
> ...or others, like myself, who simply had the decency to make their
> killfile grow by one entry. (I can take one or two replies but to be so
> relentlessly stubborn about something in black in white is too much for
> even Mother Teresa to bear.)
<ot>
about killfiles, what news-reader do you use ?
I use netscape, and I can't find if it has a killfill option.
(not that I want to use it, but I am curious)
</ot>
Regis
The amount of hours I've spent programming in C++ are incredibly
limited, so I'll take your word that wrapping this in a class would slow
things down slightly. (Besides, it seems logical.)
> So if you write code, that is not portable anyway, since it is e.g. for
> Windows or Linux or ... , then simply forget about portability, since
> this construct is much more portable, than the rest of the code.
You are comparing apples and oranges. Not portable across platforms
such as the ones you mention have nothing to do with not portable
because of undefined behaviour. If you were to program on two different
compilers for the same platform, say MSVC++ and DJGPP, you won't
necessarily be able to compile your the exact same programs.
> IMHO, if you start to use some more specialized includes and/or library-functions,
> your code starts not being portable. If you rely on minimal sizes of some
> types (e.g. int) your code won't be portable too (AFAIR int may have even as few
> as 8 bits or even less).
As Chris already pointed out, you are guaranteed *at least* 16 bits.
You may get more, though.
<quote>
5.2.4.2.1 Sizes of integer types <limits.h>
[#1] The values given below shall be replaced by constant
expressions suitable for use in #if preprocessing
directives. Moreover, except for CHAR_BIT and MB_LEN_MAX,
the following shall be replaced by expressions that have the
same type as would an expression that is an object of the
corresponding type converted according to the integer
promotions. Their implementation-defined values shall be
equal or greater in magnitude (absolute value) to those
shown, with the same sign.
<snip non-int related>
-- minimum value for an object of type int
INT_MIN -32767 // -(215-1)
-- maximum value for an object of type int
INT_MAX +32767 // 215-1
</quote>
> So take the simple loop:
>
> int i;
> for(i=0;i<1000;i++) {....}
>
> Is this portable? No, it will break on systems on which an int has only 9 bit.
But then it isn't a C compiler.
> Guess why quite some code is messed up with things like "#ifdef solaris",
> "#ifdef linux" and so on.
>
> So I see it as a trade off between simplicity of the sourcecode (and in many
> cases speed of the program) versus portability. So look at your program or
> part of code that should be reused and look which part of it is the
> least portable section. Then estimate, how much work it would be to make
> it portable and if it would be worth it. If not simply forget about
> portability for the rest.
Once again, as Chris already noted, it is better design style --
although far from necessary -- to keep your portable code separate from
your non-portable code. I, like I suspect most programmers, have made
myself a plethora of less-than-10-line-functions contained in strictly
non-ANSI/ISO C code files that serve precisely this goal -- they'll work
for Windows, but not for Linux. (OSes chosen at random.) This way,
whenever I decide to port my code, all that has to be changed are those
functions/source files although I'll know what to call my functions and
what return type they should have. In fact, at the top of every source
code file I issue a warning such as:
/*
** *NOT* ANSI/ISO C
*/
so that a utiliy like grep will allow me to track these down
effortlessly. Perhaps personal opinion/choice, but I've always liked
this method and it has never shown me any bad side effects.
>So if you write code, that is not portable anyway, since it is e.g. for
>Windows or Linux or ... , then simply forget about portability, since
>this construct is much more portable, than the rest of the code.
What exactly do you mean by ``much more portable?'' Do you mean that
it will run on every compiler that supports the rest of the code?
Now and in the future? How do you know?
>So take the simple loop:
>int i;
>for(i=0;i<1000;i++) {....}
>Is this portable? No, it will break on systems on which an int has only 9 bit.
But both C and C++ require every int to be able to store values
at least as large as 32767.
Look at:
"Edit" "Message Filters..."
> > parent(x) = x / 2
> > left_child(x) = x * 2
> > right_child(x) = left_child(x) + 1 = (x * 2) + 1
>
> Sure, because the expressions for parent, left_child, right_child
> are designed to work with "1 indexing"
>
> But if you change them, you can make them work with "0 indexing"
> too
>
> parent(x) = ( x / 2 ) - 1
> left_child(x) = ( x * 2 ) + 1
> right_child(x) = left_child(x) + 1 = ( x * 2 ) + 2
>
> Agreed: The expressions get a little bit more complicated then
> in the "1 index" case.
I think that's the point. The expressions are more natural in
the 1-base case.
I think that this case is definitely a point in favor of 1-base.
After all, you can adjust the expression to yield *any* base--0
or 1 or 42. It's just that it's simpler with 1-base.
> But there are other cases, where the opposite is true.
Certainly. I think that most of them lie on the 0-base case, but
maybe that's just because I'm so accustomed to it. Reading
mathematics sometimes makes my head spin because mathematicians,
even Knuth, tend to 1-base their vectors and matrices.
> Thanks Bjarne,
>
> And please forgive my troll.
Sure
> But there are too few carefully chosen words said
> about arrays and pointer arithmetic.
> The topic really deserves a more thorough treatment
> especially in regards to numerical computing.
> I'm sure that you are well aware that
> the trick which Chris Mears describes is common
> in numerical computing and used extensively
> in "Numerical Recipes in C" for example.
If I understand this thread correctly, you are referring to things like
int v[20];
int* p = &v[-1];
> I don't see any reason why you, Dennis or Brian
> would need to specify this in any manual
> or standards document but I don't think
> any compiler developer is going to break
> all of the existing code which relies on this trick
> if they don't need to do so. Do you?
(1) Neither standards writers nor compiler writers break code when they
don't need to. In fact, they usually go far out of their way to avoid
breaking even poor and illegal code. (However, we should not be keen to
take advantage of that).
(2) But there are good hardware reasons for code like &v[-1] to be illegal.
If I'm generating code for a machine with a segmented address space,
I want to be able to allocate arrays on segment boundaries. This is
the natural place for them and not doing so can easily waste space
(especially bad on machines with little memory or small segments).
However, if I want to support &v[-1] I cannot allocate v on a segment
boundary, because if I did, trying to form &v[-1], to load it into a
register, or to use &v[-1] in any way would cause a hardware violation
or an erroneous result (exactly what happens depends on the machine
architecture).
There are many such architectures. Consequently, the C and C++
standards prohibit &v[-1]. Obviously, the non-portable techniques
offered by "Numerical Recipes in C" (if I understood you correctly)
are not commonly used for those architectures.
Allowing &v[-1] in standard C and C++ would force C and C++
implementers for such architectures to choose between standards
conformance and reasonable implementation techniques. Traditionally,
C and C++ do not directly support facilities that map poorly to
common hardware.
(3) I haven't actually seen code written that way that I considered good
code. Often, it is a result of an attempt to use 1-based indexing rather than
0-based indexing. I don't consider that good C, and if you must use 1-based
indexing in C++, it is usually better to provide a class that offers 1-base
indexing rather than playing pointer games.
> I would argue that it is a de facto standard
> and there is nothing that you, Dennis or Brian
> could or should do about it.
I'm always leery about arguments that a "de facto standard" should take
priority over an ISO standard. The standards aren't perfect, but they are
on average much better thought out and address a much larger set of concerns
than the average "de facto standard."
It is a fact that &v[-1] works for some arrays on some machine architectures,
but it is the job of standards to point-out/warn-against uses that are not
portable and may have implementation-dependent effects.
I think that warning against dangerous and non-portable constructs it is
part of the job of a responsible designer or teacher. Especially, if the
construct appears to be innucuous, but isn't.
Indexing beyond the limits of and an array is a far-too-common error in
C and C++. It is also one of the more preventable errors. That's one reason
I recommend use of C++ standard library facilities such as vector, map,
and string rather than (direct) use of arrays, pointers, and pointer
arithmetic (for example, see "Learning Standard C++ as a New Language";
it can be downloaded from http://www.research.att.com/~bs/papers.html).
> > So if you write code, that is not portable anyway, since it is e.g.
> > for Windows or Linux or ... , then simply forget about portability,
> > since this construct is much more portable, than the rest of the code.
>
> Probably. Let's say it's about 95% portable.
> I still like 100% portable more. :)
That's wishful thinking.
Nevermind hardware. Software reasons are enough:
char i_[10];
char *i = i_-1;
assert(i != NULL);
If i_ is placed at location 1 because the compiler uses address 0 as
NULL and understandably doesn't put a valid object there, then i will
falsely (for our shadowy purposes) compare equal to NULL.
For the benefit of Tisdale, as I'm sure you already fully appreciate,
the location of i_ depends on a great variety of factors, including
optimization settings, order of declaration, presence/absence of other
variables, et al. I'll also point out the obvious fact that the
assert() (or a similar if check) will likely be located far away from
the declaration of i, possibly inside a third-party library. How long
will it take a programmer to figure out what was actually wrong?
the standard is clear about this. it is not allowed to _compute_ a
pointer that is off the beginning of an array, or more than one
element past the end.
ISO/IEC 14882:1998, section 5.7, page 84:
"If both the pointer operand and the
result point to elements of the same array object, or one past the
last
element of the array object, the evaluation shall not produce and
overflow; otherwise, the behaviour is undefined."
it will probably work most of the time, but there is no guarantee.
unfortunately, this is done frequently in numerical software.
vr
> Nevermind hardware. Software reasons are enough:
> char i_[10];
> char *i = i_-1;
> assert(i != NULL);
> If i_ is placed at location 1 because the compiler uses address 0 as
> NULL and understandably doesn't put a valid object there, then i will
> falsely (for our shadowy purposes) compare equal to NULL.
what do you mean 'falsley'? i *is* NULL, so how is the result false? using
i[0] would be a huge error (which i'm sure anyone on this thread will agree
with), so it doesn't really matter what i does or does not compare equal
with.
the issue is that in order for these pointer games to work, pointer
arithmetic must 'wrap' which isn't always the case. for example, let's
assume:
- you had a segment 10 bytes in size
- you had an int i_[5] which the compiler placed at the top of the segment
(i.e. address 0)
- you had an int *i which you assigned to i - 1. what is i equal to? what
is i[1] equal to? it depends on the implementation, so it's not really
useful in portable code.
--
/"\ m i k e b u r r e l l
\ / ASCII RIBBON CAMPAIGN mik...@home.com
X AGAINST HTML MAIL
/ \
It's false because if i were to be placed at any other address then
the assert would not (probably) not be true.
Paul
> > assert(i != NULL);
> > If i_ is placed at location 1 because the compiler uses address 0 as
> > NULL and understandably doesn't put a valid object there, then i will
> > falsely (for our shadowy purposes) compare equal to NULL.
> what do you mean 'falsley'? i *is* NULL, so how is the result false? using
> i[0] would be a huge error (which i'm sure anyone on this thread will agree
> with), so it doesn't really matter what i does or does not compare equal
> with.
[...]
What I mean by "falsely" is that the person writing the code does not
expect i to compare equal to NULL. i is supposed to be a valid object
indexable from 1 to 10. As you say, this assumption is wrong, because
one manifestation of such undefined behavior is that the resulting
object can compare equal to NULL.
>> Not every C and C++ compiler will allow you to do it.
>Which ones?
The one I'm thinking of is from a company called CenterLine
(www.centerline.com). I haven't used it in a number of years,
but when I did, one of its properties was that it checked all
pointer arithmetic to ensure that the result was in bounds.
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
Portable is generally taken to mean that the semantics is guaranteed on
all platforms. Whether you like it or not there are systems where
loading an invalid address into an address register causes your program
to terminate. An invalid address includes any address that attempts to
refer to memory that is not owned by the process. E.g.
int main(){
int * i_ptr = new int[10];
int * j_ptr = i_ptr-1;
}
Regardless as to your personal predilections the above program contains
undefined (NOT unspecified) behaviour. That means that the C++ Standard
places no requirements on the result or attempting to execute such code.
Note that this isn't even a QoI issue. In protected memory systems
anything that looks like a possible breach of memory security is stamped
on fast.
Yes it is a subtle issue and one that is well understood by those who
have been around C or C++ standards for more than a few months.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
As it is undefined behaviour the compiler is not required to diagnose
it. The resulting code might even do exactly what you expect until the
day it is run on a configurable OS that happens to object to illegal
addresses in some but not all its modes of operation. If the code
happens to be controlling something important (to the user), a core dump
is probably not appropriate.
No, it's a practical and normal reality for those who regularly write
and test code on a PC before testing and using it on a mainframe. On
such systems, you *must* be 100% portable to stand any chance of getting
a working program.
I have written many such programs, to run on two or (occasionally) three
completely different operating systems for completely different
hardware. Portability is not a nice-to-have in those situations; it's a
requirement.
> But there are too few carefully chosen words said about arrays and
> pointer arithmetic. The topic really deserves a more thorough
> treatment especially in regards to numerical computing. I'm sure
> that you are well aware that the trick which Chris Mears describes
> is common in numerical computing and used extensively in "Numerical
> Recipes in C" for example.
Of course, many would see this as (yet another) reason not to use
Numerical Recipies. ;-) My $.02
--------------------------------------------------------------------------
Dave Steffen Wave after wave will flow with the tide
Dept. of Physics And bury the world as it does
Colorado State University Tide after tide will flow and recede
stef...@lamar.colostate.edu Leaving life to go on as it was...
- Peart / RUSH
"The reason that our people suffer in this way....
is that our ancestors failed to rule wisely". -General Choi, Hong Hi
Certainly it matters. If a C compiler violates the C standard, I can
submit a bug report to the authors of the compiler and point out the
violation. Either they can fix it, or I can use a different compiler
(or, if I must, I can work around the bug).
In the absence of a standard that the compiler implementers feel
obliged to follow, there would be no hope of porting code from one
implementation to another. We wouldn't have a C language; we'd have a
family of coincidentally similar languages, probably all called C by
their authors. (Likewise for C++.)
--
Keith Thompson (The_Other_Keith) k...@cts.com <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Welcome to the last year of the 20th century.
And neither can they, either before, during, or after.
So please, don't keep saying that they did.
>> This leads me to believe that
>> one or more of the following seems to be the case:
>> 1) You're wrong.
>> 2) You're not stating your point well.
>> 3) I'm not understanding your point for some reason.
>
>Maybe. But I don't think so.
Then present from facts, or put an end to this.
>My opinion is based upon published remarks
>made by the C and C++ language designers.
Quote them here, exactly and in context, or put an end to this.
>I might try to collect them all together some day
I'll make it simpler: post just one, or put an end to this.
>but it would probably be better
>if they addressed the issue directly themselves
>instead of relying on my (or anyone else's)
>interpretation of their remarks.
You're the one who spoke for them, quite animately so,
but now you want to slither away. Fine, thank you for
putting an end to this.
- Greg
--
Comeau Computing, Producers of Comeau C/C++ 4.2.42 (4.2.43 BETA starting)
Try Comeau C++ online at http://www.comeaucomputing.com/tryitout
Email: com...@comeaucomputing.com / WEB: http://www.comeaucomputing.com
Sorry, I don't know what you mean. You see, I have my own
version of English. Yes, we're both being silly.
Sigh.
>But there are too few carefully chosen words said
>about arrays and pointer arithmetic.
>The topic really deserves a more thorough treatment
>especially in regards to numerical computing.
>I'm sure that you are well aware that
>the trick which Chris Mears describes is common
>in numerical computing and used extensively
>in "Numerical Recipes in C" for example.
>I don't see any reason why you, Dennis or Brian
>would need to specify this in any manual
>or standards document but I don't think
>any compiler developer is going to break
>all of the existing code which relies on this trick
>if they don't need to do so. Do you?
But the compiler developer may not have a chance in some cases,
and so there isn't always something they can do about it.
>I would argue that it is a de facto standard
>and there is nothing that you, Dennis or Brian
>could or should do about it.
I would argue that such "practice" is bad programming.
For instance, just because *(char*)0 = 'x'; works on
many machines is not a good reason to make it a technique,
nor so with the above.
Please post specific examples of these "important existing programs".
> I would argue that such "practice" is bad programming.
> For instance,
> just because *(char*)0 = 'x'; works on many machines
> is not a good reason to make it a technique,
> nor so with the above.
I'm not arguing that there is a good reason
to make *(char*)0 = 'x'; a technique
or that it isn't bad programming practice.
> Sure, because the expressions for parent, left_child, right_child
> are designed to work with "1 indexing"
Come to think of it, yes they are designed for that.
> But if you change them, you can make them work with "0 indexing"
> too
> parent(x) = ( x / 2 ) - 1
> left_child(x) = ( x * 2 ) + 1
> right_child(x) = left_child(x) + 1 = ( x * 2 ) + 2
Why make it more complicated and less efficient than it needs to be?
> Agreed: The expressions get a little bit more complicated then
> in the "1 index" case. But there are other cases, where the
> opposite is true.
Yes, there is more math involved in the 0-index case. That was precisely
my point. Someone asked for an example of where 1-index made more sense
than 0-index, and I provided one: representing a tree as an array.
-Adam
"E. Robert Tisdale" wrote:
>
> All I'm saying is that
> if you start implementing C++ compilers that reject code
> which computes addresses off the beginning of arrays
> a lot of important existing programs aren't going to compile
> and you will have trouble selling your compilers
> to your customers no matter how furiously
> you wave the standards documents at them.
If you had actually read the responses, you would
have noticed, that a lot of people have given the
hint, that there is hardware, where even "forming"
this adress in a register is illegal.
So please. Before you make a complete fool out of yourself:
stop this thread.
To summarize the replies of 3 days (!)
The standard says, that if you subtract before an array
you enter undefined behaviour land. Anything can happen,
including what you were expecting. But as "undefined" says:
you can't rely on this behaviour.
The fact, that a lot of compiler/OS/hardware give the right
result, is a coincidence which says nothing.
The fact that any combination of compiler/OS/hardware can
reject this code is *not* the problem of the compiler writer,
but it is the problem of the writer of the code.
It's way too late for that.
>stop this thread.
Indeed.
<snip>
--
Richard Heathfield
Laptopped.
"Thank God for semi-colons." - Dilbert
> * E. Robert Tisdale
> > Andrew Koenig wrote:
> >
> > > In article <n7qhis420cmc1l110...@4ax.com>,
> > > Andras Erdei <c...@freemail.c3.hu> wrote:
> > >
> > > > int i_[ 10 ] ;
> > > > int * const i = i_ - 1 ; /* i_[ j ] == i[ j + 1 ] */
> > >
> > > Please, not again.
> > >
> > > The computation of i_ - 1 has undefined effect,
> > > because you're not allowed to compute an address
> > > that's off the beginning of an array
> > > (or that's more than one element off the end).
> >
> > Nonsense!
> >
> > It will work almost everywhere.
> The standard is clear about this.
You probably mean the standards document.
> It is not allowed to _compute_ a pointer
> that is off the beginning of an array,
> or more than one element past the end.
>
> ISO/IEC 14882:1998, section 5.7, page 84:
>
> "If both the pointer operand and the result
> point to elements of the same array object,
> or one past the last element of the array object,
> the evaluation shall not produce and overflow;
> otherwise, the behavior is undefined."
>
> It will probably work most of the time,
> but there is no guarantee.
>
> Unfortunately,
> this is done frequently in numerical software.
The standards documents are NOT the standard
any more than that ancient piece of parchment
enshrined in glass in our nation's capital
is the Constitution of the United States of America.
The standard is the entire collection documents,
expert opinion, compiler implementations and
common usage of the language.
This so-called defacto standard usually supersedes
and overrides any standard de jure.
Good C and C++ programmers don't rely
on the standards documents alone to ensure portability.
They use the C preprocessor, for example, to test macros
defined for the machine architecture and the compiler
then include appropriate code for each case.
There probably aren't any large and useful C or C++
programs that can be guaranteed to port
to every existing or future combination
of architecture and compiler.
Portability is merely one of the goals
that programmers may have for their code.
It does not, by itself, distinguish good code from bad.
"E. Robert Tisdale" <ed...@netwood.net> wrote
>
> Which ones?
> Which ones?
> Which compiler won't accept it?
> Which compiler are you talking about?
I can't speak for Andrew, but Win16 and OS/2 1.x can both
fall over on this trick. In their day, these were quite
widely used platforms, and had numerous compilers.
For example, if we had a member variable...
double __huge* p;
...and we initialised it in the constructor with...
p = new double[10000] - 1;
...then there is a reasonable probability that when we write...
for (int i=1; i<=10000; ++i)
p[i]; // use it in some way
...then the program will go "pop". The reason is that the Intel
processor has dedicated registers for addresses, and loading an
invalid address into them results in a protection fault. In this
example, whilst p[i] is valid, the assembly code probably loads
"p" and uses the indexed addressing mode to add "i" on the fly.
> Portable is generally taken to mean that
> the semantics is guaranteed on all platforms.
Who guarantees it?
Can I sue the standards committee
if my standard conforming code breaks?
> Whether you like it or not, there are systems
> where loading an invalid address into an address register
> causes your program to terminate.
Which system does this?
> An invalid address includes any address
> that attempts to refer to memory
> that is not owned by the process. E.g.
>
> int main() {
> int * i_ptr = new int[10];
> int * j_ptr = i_ptr - 1;
> }
This does NOT attempt to refer to memory
that is not owned by the process.
> Regardless as to your personal predilections,
> the above program contains undefined (NOT unspecified) behavior.
> That means that the C++ Standard places no requirements
> on the result or attempting to execute such code.
The above program contains NO behavior at all
except for an allocation of ten int's from the free store.
A good C++ compiler would optimize away the j_ptr pointer object
because it is never used.
> Note that this isn't even a QoI issue.
> In protected memory systems,
> anything that looks like a possible breach of memory security
> is stamped on fast.
I don't know of any "protected memory system"
which prevents you from computing any address.
They don't fault unless you actually try to access data
in memory that does not belong to you.
> Yes it is a subtle issue and one that is well understood
> by those who have been around C or C++ standards
> for more than a few months.
I've "been around" C and C++
as long as there has been a C and C++.
How long have you been around?
> In article <392B17D6...@netwood.net>,
> E. Robert Tisdale <ed...@netwood.net> wrote:
>
> >> Not every C and C++ compiler will allow you to do it.
>
> >Which ones?
>
> The one I'm thinking of is from a company called CenterLine
> (www.centerline.com).
I checked them out.
They "Support for leading UNIX workstations."
> I haven't used it in a number of years,
> but when I did, one of its properties was that it checked all
> pointer arithmetic to ensure that the result was in bounds.
That seems like a good option for any C or C++ compiler
given the specification in the standards documents.
But does it mean that the compiler will not emit code
to form an address off the beginning of an array?
I'd ask them myself but I don't want to bother them
because I'm not interested in buying one of their compilers --
especially if it can't generate code to compute addresses
off of the beginning of an array.
> Andrew said, "you're not allowed to compute an address
> that's off the beginning of an array".
> That's nonsense.
> You can, indeed, compute an address
> that's off the beginning of an array
> and every C and C++ compiler will allow you to do it.
Even if they did, it is more than possible that computing an address
before the beginning of an array is an invalid address _to the
hardware_, causing a trap merely by being computed, let alone used, and
there's nothing any C compiler can do about that.
> > Are you endorsing deliberate ignorance of the standards?
> > Do you *really* want to go off into undefined behavior land
> > when there is a perfectly good alternative?
> > Or are you just being difficult?
>
> No.
> You're the one who is ignoring the standards.
> You think that the standards documents are the standards.
> They are not. They are only one component of the standards.
> They are a formal articulation of the standards.
> You must also consider expert interpretation of the standards,
> actual implementations of compilers
> and how the languages are actually used in practice.
Ahem. So void main() is standard? fork()? clrscr()? refresh()?
_WIN_PleaseDoNotCrashMyMachine()? All of these (ok, except maybe the
last one) are actually used in practice by many people. Must we
therefore accept them as standard and as on-topic for comp.lang.c(++)?
I think you'll agree that that would be ridiculous. So why accept any
other non-Standard behaviour as standard?
> > However, this is definitely not portable.
>
> But it is, in fact, way portable.
> The standards documents may indicate
> that the behavior is undefined
> but that has no practical meaning
> to most compiler developers
> because trick is used in thousands of existing
> C and C++ programs.
So is gets(). So is, indeed, getch().
> They might implement a C or C++ compiler
> which would refuse to accept your example
> or emit code which did something unexpected
> but nobody would buy or use their compiler.
I would. By preference, in fact. At least I'd know what I would have to
look out for.
Richard
yes, of course.
> > It is not allowed to _compute_ a pointer
> > that is off the beginning of an array,
> > or more than one element past the end.
> >
> > ISO/IEC 14882:1998, section 5.7, page 84:
> >
> > "If both the pointer operand and the result
> > point to elements of the same array object,
> > or one past the last element of the array object,
> > the evaluation shall not produce and overflow;
> > otherwise, the behavior is undefined."
> >
> > It will probably work most of the time,
> > but there is no guarantee.
> >
> > Unfortunately,
> > this is done frequently in numerical software.
>
> The standards documents are NOT the standard
> any more than that ancient piece of parchment
> enshrined in glass in our nation's capital
> is the Constitution of the United States of America.
I really can't relate to this since I'm not from the United States of
America. .. but you (as in "you americans") refer to the bill of right
all the time, right?
> The standard is the entire collection documents,
> expert opinion, compiler implementations and
> common usage of the language.
> This so-called defacto standard usually supersedes
> and overrides any standard de jure.
>
> Good C and C++ programmers don't rely
> on the standards documents alone to ensure portability.
> They use the C preprocessor, for example, to test macros
> defined for the machine architecture and the compiler
> then include appropriate code for each case.
>
> There probably aren't any large and useful C or C++
> programs that can be guaranteed to port
> to every existing or future combination
> of architecture and compiler.
> Portability is merely one of the goals
> that programmers may have for their code.
> It does not, by itself, distinguish good code from bad.
I'm not sure which of my statements you're arguing against here. I'm
saying that if you want your code to work on all compilers, you'll
have to follow the standards document. You seem to agree. Am I right?
But; if you're going to do things not allowed by the standards, be
sure to check the compiler documentation, and do not rely on emirical
data.
vr
> There probably aren't any large and useful C or C++
> programs that can be guaranteed to port
> to every existing or future combination
> of architecture and compiler.
> Portability is merely one of the goals
> that programmers may have for their code.
> It does not, by itself, distinguish good code from bad.
Insisting on using constructs that produce undefined behavior, for no
other reason than being obnoxious, is a behavior that, by itself,
distinguishes bad programmers from good ones.
And of course, using non-portable constructs in code ***that is designed
to be portable***, like the "Numerical Recipes in C", DOES distinguish bad
code from good one.
>> I haven't used it in a number of years,
>> but when I did, one of its properties was that it checked all
>> pointer arithmetic to ensure that the result was in bounds.
>That seems like a good option for any C or C++ compiler
>given the specification in the standards documents.
>But does it mean that the compiler will not emit code
>to form an address off the beginning of an array?
It will emit code that, when executed, causes the program to
halt and transfer control to the debugger.
Now, here's the point. You started out by saying that
C and C++ were really whatever the implementations defined
them to be. I've shown you that there is an implementation
that does not allow you to form an address that's off the
beginning of an array.
I'm willing to accept that you personally dislike that
implementation. But suppose you wanted to convince the
vendor that they should change their implementation. Do
you have any objective arguments that you can make?
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
[...]
) ...then the program will go "pop". The reason is that the Intel
) processor has dedicated registers for addresses, and loading an
) invalid address into them results in a protection fault. In this
Are you really sure about that? Does loading the register alone
with a "wrong" value give a protection fault, or is it the actual
accessing of the memory? The latter case should be no problem in
general, since even when there is some wraparound in address calculation,
this wraparound is eliminated by the second wraparound, that occurs
when accessing array elements.
A problem would be, if the address registers would use some sort
of saturation instead of wraparound, since in this case you would
get wrong addresses. But I know of none processor that works this
way with addresses.
OK, here comes a list, which tries to show where you most likely will
see problems:
- Special processors, that don't allow to load address registers with
arbitrary data.
- Special processors, that don't have wraparound on address calculations
- Compilers that try to support bounds checking
- C/C++ interpreters
- Really fancy optimizing compilers
But as I have written before: Anybody must decide for herself/himself, for
every piece of code, if it is worth to keep the code portable or to leave
this path for some reasons (performace, readability, color of your shirt,
or whatsoever). E.g. if you write code, that depends on compiler specific
extensions anyway, why bother if some other construct in the same piece of
code is portable?
- Matthias Meixner
--
Matthias Meixner mei...@rbg.informatik.tu-darmstadt.de
Technische Universität Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstraße 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
> If you had actually read the responses,
> you would have noticed,
> that a lot of people have given the hint,
> that there is hardware,
> where even "forming" this address in a register is illegal.
> The standards document says that
> if you subtract before an array you enter undefined behavior land.
> Anything can happen, including what you were expecting.
> But as "undefined" says: you can't rely on this behavior.
> The fact, that a lot of compiler/OS/hardware give the right result,
> is a coincidence which says nothing.
The fact is that almost every compiler/OS/hardware combination
gives the right result and, apparently, you can't think of one
that does not.
Sailors don't worry about icebergs in tropical waters
and programmers who write portable applications
don't worry about calculating addresses off the beginning of an array.
It borders on superstitious belief.
There are too many more likely pitfalls to worry about
to be bothered by the possibility that their code might break
in the unlikely event that someone tries to port it
with a compiler which emits code
to "form" addresses in deficient registers.
> The fact that any combination of compiler/OS/hardware
> can reject this code is *not* the problem of the compiler writer,
> but it is the problem of the writer of the code.
No.
It's the compiler developers' problem
if they can't get programmers to use their compiler
because it won't compile the programmers' code.
Programmers will just buy somebody else's compiler.
1) I am toying with the Traveling Salesman's Problem, for which there is
a nice library of test problems, TSPLIB (mirror site at Rice
University). All the vertex coordinates in the problems are labeled with
integers starting at one.
It wouldn't be difficult to convert that to zero-based indexing when
reading the problem in, but I'd have to convert it back to one-based
later when I wanted to compare my answer to the published solutions.
It's easier just to allocate an extra element and not use it.
2) Ah heaps, particularly those implemented as arrays where the element
at index 'n' has children at '2n' and '2n+1'. But what's 2 * 0, hmm?
Oh, you can fiddle around with the definition and use a different
formula, I suppose, but then your code no longer matches most, if not
all, textbook treatments of this topic. So then who can read your code?
- Anton
--
comp.lang.c.moderated - moderation address: cl...@plethora.net
Their undefined behavior approach was with version 1 of NR in C. They
acknowledged the bug, and fixed it in the subsequent edition. The real
reason not to use any edition of NR in C is that the code is icky[tm]. The
newer addition just allocates DIM+1 whenever an array of size DIM is needed.
Does not sound so bad, but consider a 6x6x6 array compared to 5x5x5 and you
will see that there can be considerable waste.
Actually, some of the code is not terrible, but the one based arrays [see
thread title] are enough of a reason to throw it out. How many pre-written
packages will interface with that mess!
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. Newsgroup http://www.dejanews.com/~c_a_p
C.A.P. FAQ: ftp://38.168.214.175/pub/Chess%20Analysis%20Project%20FAQ.htm
>In fact, it will work almost everywhere. And, I believe that
>if Brian W. Kernighan, Dennis M. Ritchie and Bjarne Stroustrup
>had their way the standards documents would clearly state
>that it should work everywhere.
Here's what Kernighan and Ritchie actually said
(in ``The C Programming Language, second edition, page 205):
The result of the + operator is the sum of the operands.
A pointer to an object in an array and a value of any
integral type may be added. The latter is converted to
an address offset by multiplying it by the size of the object
to which the pointer points. The sum is a pointer of the same
type as the original pointer, and points to another object
in the same array, appropriately offset from the original
object. Thus if P is a pointer to an object in an array,
the expression P+1 is a pointer to the next object in the
array. If the sum pointer points outside the bounds of the
array, except at the first location beyond the high end,
the result is undefined.
I think that's crystal clear.
Because portability is not a binary attribute. For example, if I
have a 10,000 line program in which one function must handle a
hardware interrupt (which we all know is almost completely non-
portable), porting this program may be as simple as rewriting
that function and recompiling. In some cases, I may even be able
to simply remove that feature and still have a useful program.
However, if I followed your advice, I may have 5,000 other things
to fix, assuming I even knew what the original programmer expected
of each specific undefined behavior.
Would you expect them to contradict the standards document
in "The C Programming Language, second edition"?
I think that Bjarne has already explained pretty well
why the standards documents can't specify
that this trick should work everywhere
even if it does work almost everywhere and
even if a lot of existing code depends upon it.
Why is this disallowed in the first place?
There should be a valid reason. If not, then we
should take note and amend the rule when we get
at the next iteration of the standards (C, C++).
I guess there is no point arguing about this.
Some people follow rules, some people don't.
It's like stopping on a red light when the
intersection is empty anyway.
Also, why do we need 1 based indexing in the
first place? Does it make a difference?
Readability? Nah don't give me that. It's
a pain to shift gears comprehending 0 based
and 1 based code. Imagine a math program where
programmers arbitrarily mix 1 based and 0 based
codes. And you're next in line to maintain it.
hell!!!
Unless there are performance concerns, I see no
reason why we need 1 based indexing.
Joel de Guzman
> It will emit code that, when executed,
> causes the program to halt and transfer control to the debugger.
That's great for debugging.
What happens when you turn off debugging?
> Now, here's the point.
> You started out by saying that C and C++
> were really whatever the implementations defined them to be.
> I've shown you that there is an implementation
> that does not allow you to form an address
> that's off the beginning of an array.
>
> I'm willing to accept that you personally dislike that implementation.
> But suppose you wanted to convince the vendor
> that they should change their implementation.
> Do you have any objective arguments that you can make?
I do NOT dislike the implementation.
If all C and C++ compilers had been implemented that way,
we wouldn't have this problem.
But the fact is that almost no C or C++ compilers
were or are implemented that way
and C and C++ programmers have a huge body of legacy code
which will break if all compiler developers start implementing
their compilers this way.
I don't know anything about the centerline C and C++ compilers
except that the do emit code for hardware
that is capable of computing and representing addresses
off of the beginning of an array.
My expectation is that the code emitted by these compilers
will behave as expected when you turn off debugging.
I would guess that there is a debugger option to turn off
the trap for address computations off the beginning of an array
so that programmers can debug their code without tripping it
every time their code executes.
My only advice to the vendor is to implement their compilers
so that they can sell them to as many programmers as possible
and make make as much money as possible.
I don't think that I could be more objective than that.
>Would you expect them to contradict the standards document
>in "The C Programming Language, second edition"?
Irrelevant question. You made a prediction about what Kernighan and
Ritchie would say if they had the chance. They did have the chance,
and they said something different from what you predicted.
>) ...then the program will go "pop". The reason is that the Intel
>) processor has dedicated registers for addresses, and loading an
>) invalid address into them results in a protection fault. In this
>Are you really sure about that? Does loading the register alone
>with a "wrong" value give a protection fault, or is it the actual
>accessing of the memory?
Both.
The point is that loading an address into a segment register causes
page translation to be done at that point, complete with
validity checking. By using that strategy, the processor can
avoid having to redo the page translation at every reference.
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
He also made a prediction about what Bjarne Stroustrup would say if he
had the chance.
Mr Stroustrup did indeed have the chance, and took full advantage of it
to firmly contradict Mr Tisdale's rather cavalier stance.
Demigods United 3, Tisdale Wanderers 0.
Game over.
--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
37 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (60
to go)
And all the expert opinion we've seen here, including Bjarne
Stroustrup (who recently posted a followup to this thread), as well as
Kernighan and Ritchie (in a passage quoted from K&R2), says that
computing an address before the beginning of an array invokes
undefined behavior and is non-portable.
On the other hand, you have yet to demonstrate that computing such an
address is "common usage".
> Karl Heinz Buchegger wrote:
>
> > The fact that any combination of compiler/OS/hardware
> > can reject this code is *not* the problem of the compiler writer,
> > but it is the problem of the writer of the code.
>
> No.
> It's the compiler developers' problem
> if they can't get programmers to use their compiler
> because it won't compile the programmers' code.
> Programmers will just buy somebody else's compiler.
Hm. If it doesn't compile, just buy another compiler. Wow, that's a
debugging method I haven't tried yet ;-)
--
Nils Goesche
Ask not for whom the <CONTROL-G> tolls.
<snip>
> If all C and C++ compilers had been implemented that way,
> we wouldn't have this problem.
> But the fact is that almost no C or C++ compilers
> were or are implemented that way
> and C and C++ programmers have a huge body of legacy code
> which will break if all compiler developers start implementing
> their compilers this way.
Apart from Mr Tisdale, has any C or C++ programmer seen any evidence of
this "huge body of legacy code"? I know I haven't.
C programmers.
Yes, he means the ISO document which defines what C is, so that everyone
(except you) can be sure of what C is.
> The standards documents are NOT the standard
> any more than that ancient piece of parchment
> enshrined in glass in our nation's capital
> is the Constitution of the United States of America.
This is, I think, at the centre of your problem. You seem to think that
the nation you happen to live in is the whole world, and that the
compiler you happen to use is the whole language. You're wrong on both
counts.
> The standard is the entire collection documents,
> expert opinion, compiler implementations and
> common usage of the language.
> This so-called defacto standard usually supersedes
> and overrides any standard de jure.
Congratulations on your rare ability to spell 'supersede' correctly, a
most underrated talent.
As for the rest of this paragraph, it's complete nonsense. The Standard
is an abstract concept, but it's sufficiently solid to have a clearly
discernible meaning in the real world of C (and, since this is
cross-posted, the C++ Standard, too, has a clearly discernible meaning
in the real world of C++) programming, so that all those who want to
write portable code can do so. Clearly you are not interested in writing
portable code. If you were, you would understand why the Standard is
important.
>
> Good C and C++ programmers don't rely
> on the standards documents alone to ensure portability.
> They use the C preprocessor, for example, to test macros
> defined for the machine architecture and the compiler
> then include appropriate code for each case.
You seem to be suggesting that a portable program is full of conditional
compilation. It ain't necessarily so. It is possible, and indeed
relatively easy, to write programs which can port to any hosted
implementation without change, and without conditional compilation.
Naturally, there will be exceptions. Equally naturally, freestanding
implementations differ slightly in this regard, since they may not have
the whole of the standard library available to them.
>
> There probably aren't any large and useful C or C++
> programs that can be guaranteed to port
> to every existing or future combination
> of architecture and compiler.
> Portability is merely one of the goals
> that programmers may have for their code.
> It does not, by itself, distinguish good code from bad.
It is true that portable code is not necessarily good code, and it is
true that non-portable code is not necessarily bad code. But your
estimate of the level of program complexity above which portable code
"probably" cannot be written is alarmingly low, probably as a result of
your attitude to portability. "Portability is not practical, therefore I
won't try to do it, therefore I'll write non-portable code, therefore
portability is not practical, QED". Fortunately, not all programmers
think like that.
E.R.T. must have thousands of them.
;-)