Topic: &array[-3] allowed?
Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: 1998/10/20 Raw View
J. Kanze wrote:
....
> C doesn't have rvalues. An expression has the quality of being an
> lvalue, or it doesn't, but there is never any need of an "rvalue
> conversion." An lvalue works equally well in expressions which don't
> require the quality. The expression above has the quality of being an
> lvalue. (But what that means with regards to any necessary access is
> not specified by the standard.) IMHO, whether v is read or not is
> either implementation defined or undefined.
>=20
> I believe that the C standards committee are in the process of refining
> this definition (or the definition of volatile access); the above refer=
s
> to C89, but perhaps not to C9x.
In C9X, there's a footnote that says
| What is sometimes called =91=91rvalue=92=92 is in this International St=
andard
| described as the =91=91value of an expression=92=92.
That's the only occurance of 'rvalue' in the entire document.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: markw65@my-dejanews.com
Date: 1998/10/21 Raw View
In article <m3n26s60mt.fsf@gabi-soft.fr>,
kanze@gabi-soft.fr (J. Kanze) wrote:
> AllanW@my-dejanews.com writes:
>
>
> |> > Going back to the original:
> |> >
> |> > v;
> |> >
> |> > Is that an lvalue or rvalue expression? In which language?
>
> C doesn't have rvalues. An expression has the quality of being an
> lvalue, or it doesn't, but there is never any need of an "rvalue
> conversion." An lvalue works equally well in expressions which don't
> require the quality. The expression above has the quality of being an
> lvalue. (But what that means with regards to any necessary access is
> not specified by the standard.) IMHO, whether v is read or not is
> either implementation defined or undefined.
C doesnt use the *term* rvalue, but 6.2.2.1 says:
Except when it is the operand of the sizeof operator, the unary & operator,
the ++ operator, the -- operator, or the left operator of the . operator or
an assignment operator, an lvalue that does not have array type is converted
to the value stored in the designated object (and so is no longer an
lvalue)...
Which appears to me to explicity require the value of v to be read in the
statement "v;"
On the other hand C++ has a different rule (5 para 8)... that an lvalue to
rvalue conversion only takes place when an lvalue is used as the operand of an
operator which requires an rvalue. Since no such operator is present in the
statement "v;" its value should presumably not be read.
Mark Williams
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/10/21 Raw View
"James Russell Kuyper Jr." <kuyper@wizard.net> writes:
|> J. Kanze wrote:
|> ....
|> > C doesn't have rvalues. An expression has the quality of being an
|> > lvalue, or it doesn't, but there is never any need of an "rvalue
|> > conversion." An lvalue works equally well in expressions which don't
|> > require the quality. The expression above has the quality of being an
|> > lvalue. (But what that means with regards to any necessary access is
|> > not specified by the standard.) IMHO, whether v is read or not is
|> > either implementation defined or undefined.
|> >
|> > I believe that the C standards committee are in the process of refining
|> > this definition (or the definition of volatile access); the above refers
|> > to C89, but perhaps not to C9x.
|>
|> In C9X, there's a footnote that says
|>
|> | What is sometimes called =91=91rvalue=92=92 is in this International
|> | Standard
|> | described as the =91=91value of an expression=92=92.
|>
|> That's the only occurance of 'rvalue' in the entire document.
Exactly. In C++, an expression is either an rvalue or an lvalue. If an
lvalue is required, then an lvalue must be given. If an rvalue is
required, there is an implicite lvalue to rvalue conversion (which in
fact may change the type: const int becomes simply int).
In C, lvalue-ness is a characteristic which an expression either has or
doesn't have. A given context either requires this characteristic or it
doesn't. There is never any need for a conversion, if the
characteristic isn't required, then any expression, whether it has the
characteristic or not, will do.
The practical results of the two ways of looking at the subject are very
similar; with built-in types, I don't think that there is any possible
way of distinguishing them. But philosophically, they are distinctly
different.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/10/17 Raw View
Joe Keane wrote:
>
> In article <F0MLDC.1M4@research.att.com>
> Andrew Koenig <ark@research.att.com> writes:
> >Consider:
> >
> > int& set(int& x, int y)
> > {
> > x = y;
> > return x;
> > }
> >
> >Looking at this function, many programmers will be tempted to rewrite
> >it as
> >
> > int& set(int& x, int y)
> > {
> > return x = y;
> > }
>
> That code is dumb.
>
> Despite the facile syntax, it's not returning a value. The function
> returns a reference, to be more explicit, it's passing back the caller
> a pointer to some location that it can modify.
>
> I don't know why someone would think that "x = y" should be a location
> that you can modify. It looks like an assignment operation to me.
> But maybe i'm missing the subtlety of the great C++.
This is exactly the sort of thing that crops up in templates. Sure, if
you're dealing with ints, you wouldn't be likely to return a reference.
But if you're writing a template that may be instantiated for a more
heavyweight type, then you'll put in the & just to avoid the copy. If
the function is further declared inline, then the compiler can tell, in
the case of ints, that the reference is (in most cases) superfluous.
--
Ciao,
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/10/20 Raw View
ark@research.att.com (Andrew Koenig) writes:
|> In article <702lsf$bqn$1@rocky.jgk.org>, Joe Keane <jgk@jgk.org> wrote:
|>
|> > That code is dumb.
|>
|> ...which is just an impolite way of saying that you don't like it.
Or that it is bad code, but I'm not going to tell you why.
The exact example posted, without further explination, is bad code, and
wouldn't pass any reasonable code review. However, there are more
complicated cases involving class types where the trade-offs are less
evident. (That is: this idiom is always bad, but in some cases, the
alternatives may all be worse.)
Anyway, I would agree that it is not a good idea for assignment to be an
lvalue. On the other hand, for the reasons you (Andy) point out, I'm
not sure that the alternatives aren't worse. In this case, C++ may be
"locally optimal"; the language could certainly be improved, but only by
changing it into another language, based on another philosophy.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/10/20 Raw View
AllanW@my-dejanews.com writes:
|> > nv = (v = 0);
|>
|> kanze@gabi-soft.fr (J. Kanze) wrote:
|> > : > one would expect the above expression to mean exactly the same as:
|> > : > v = 0 ;
|> > : > nv = v ;
|>
|> AllanW@my-dejanews.com wrote:
|> > : I wouldn't expect this. Or, rather, I would expect that
|> > : temp = 0;
|> > : v = temp;
|> > : nv = temp;
|> > : was just as valid.
|>
|> jpotter@falcon.lhup.edu (John Potter) wrote:
|> > The value of = in C++ is an lvalue; so, I would expect it to be the
|> > left operand. Now an lvalue to rvalue conversion is required which is
|> > an access. The two forms may well be the same and not at all the same
|> > as this one.
|>
|> I've just spent two hours trying to write a clear and yet extremely
|> detailed account of why my interpretation was the only correct one.
|>
|> I failed! I am now absolutely convinced that if operator= returns
|> an lvalue, then
|> nv = (v = 0);
|> must write into v, and then re-read the value back out again -- just
|> as James spelled out above. Perhaps what I wrote above would work in
|> C, I don't know any more.
I think that the vagueness is intentional, at least partially. In C, at
the time C was written, there wasn't anything portable you could do with
volatile anyway. Trying to word an exact definition of something that
is inherantly unportable is an overwhelming task, and really not
necessary, because conformance to the standard is really only an issue
with regards to portability.
|> May I please ask someone on the C++ standardization committee to explain
|> WHY the result of operator= is an lvalue? Are we trying to support code
|> such as
|> ((v = 3) = 5) = 7;
|> which now seems to be legal, and even works on my compiler? What's the
|> point of this?
This expression is undefined behavior, because it modifies v more than
once without an intervening sequence point. Note that volatile won't
help here, because it only guarantees that the actual read and/or write
will occur before the next sequence point.
|> > Going back to the original:
|> >
|> > v;
|> >
|> > Is that an lvalue or rvalue expression? In which language?
C doesn't have rvalues. An expression has the quality of being an
lvalue, or it doesn't, but there is never any need of an "rvalue
conversion." An lvalue works equally well in expressions which don't
require the quality. The expression above has the quality of being an
lvalue. (But what that means with regards to any necessary access is
not specified by the standard.) IMHO, whether v is read or not is
either implementation defined or undefined.
I believe that the C standards committee are in the process of refining
this definition (or the definition of volatile access); the above refers
to C89, but perhaps not to C9x.
In C++, the expression is an lvalue. It can be converted into an
rvalue, but in this context, I don't think it should be. Intuitively,
the lvalue to rvalue conversion is simply "reading the value", at least
for built-in types. So there is certainly an argument that v should not
be read.
|> I am still convinced that this is an lvalue expression in either
|> language (C or C++). (Remember that lvalues can be converted into
|> rvalues, so really the answer is "both".)
I think that this is one place where the two languages differ,
intentionally. The C model doesn't work well with references or member
functions. In C, the "lvalue" characteristic might be summarized by the
idea of "being an object"; the definition of an lvalue (in C) is "an
expression that designates an object", where an object is "a region of
data storage". This definition doesn't work in C++, where rvalues of
class type must also be "regions of data storage" in order to call
member functions on them.
|> But the question was,
|> does this require an access to v's value? If so, is it a read
|> access or a writeaccess -- and if it's a write access, what is
|> written?
|>
|> I still feel that this should be a no-op, even if v is volatile,
|> but I'm no longer as certain as I once was...
As I said, I don't really thing that the standard is all that clear.
For example, even if it requires an access, it doesn't specify what type
of access, and the meaning of an access is implementation defined. I
would suggest a third type of access, a "noop" access.
In a more pratical case:
v = 0 ;
the C standard can certainly be read to require a final read access of
v. In practice, no compiler I know of generates this access. For
programming hardware ports, such an access would render C totally
unusable, and so it is fairly safe that regardless of what the standard
really says (and no one seems to really know), no compiler is going to
generate the access.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/10/10 Raw View
In article <6vg6qb$s28$1@nnrp1.dejanews.com>, <AllanW@my-dejanews.com> wrote:
> May I please ask someone on the C++ standardization committee to explain
> WHY the result of operator= is an lvalue? Are we trying to support code
> such as
> ((v = 3) = 5) = 7;
> which now seems to be legal, and even works on my compiler? What's the
> point of this?
Consider:
int& set(int& x, int y)
{
x = y;
return x;
}
Looking at this function, many programmers will be tempted to rewrite it as
int& set(int& x, int y)
{
return x = y;
}
This seemingly obvious rewrite will fail miserably unless = returns a reference.
There are lots of other, more realistic examples involving class types.
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/10/10 Raw View
In article <3619686F.35DB@sig.please>, Chris Kuan <look@sig.please> wrote:
> > In principle -- but is it correct? It says that "the constraints on the
> > operators still apply." Do the constraints include the one that says
> > that the operand of * must be a valid address?
> The only constraints that I can find on the operators are:
I just came back from the C++ standards meeting, at which this issue
was discussed among others. Turns out that "constraints" mean "compile-time
constraints" in the C draft, so the quote makes sense.
I think it is likely that the C++ committee will adopt this idea in the
fullness of time. My best estimate of what will happen is that at some
point we will issue some kind of encouragement for vendors to extend the
C++ standard in particular ways, this being one of them.
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fred@genesis.demon.co.uk (Lawrence Kirby)
Date: 1998/10/12 Raw View
In article <6vcbkb$on5$1@rocky.jgk.org> jgk@jgk.org "Joe Keane" writes:
>
>In article <36119ED3.C6864ABA@ix.netcom.com>
>Paul D. DeRocco <pderocco@ix.netcom.com> writes:
>>But what does it mean to "dereference" a pointer, really? It can mean
In C it means to form an lvalue designating the object that the pointer
was pointing at (assuming the pointer had a pointer to an object type and
pointed to a valid object of that type).
>>either to read through it or to write through it, and nothing else. But
>>one of the purposes of the volatile keyword is to allow C/C++ to access
>>memory-mapped I/O ports. In this case, reading *z may access a
>>completely different register from writing *z. So which register should
>>&*z access? Obviously, it can't write *z, because it doesn't know what
>>to write. But why should it read *z, either, since it doesn't need the
>>value? Intuitively, I wouldn't expect &*z either to read _or_ write. But
Taking the address of an object doesn't access it. The current draft of
C9X (the forthcoming revision of the C standard states explicitly that &*z
behaves the same as plain z (except that it isn't an lvalue), as long as
z represents an expression that fulfils the constraints for unary *.
>>perhaps that's just a perception borne of twenty years of assembly
>>language programming. For instance, the x86 LEA instruction doesn't
>>complain if its operand refers to un-mapped memory, and &*z seems like a
>>C/C++ equivalent to LEA.
LEA corresponds to plain &, not &*.
>That's my understanding.
>
>I tend to think that people have a misunderstanding of C here, but it's
>certainly a subtle point so i don't think people are dumb or anything.
>
>I'd say, by itself, a star operator, or arrow or brackets, creates a
>memory *operand*, that is, a potential memory access. Then it depends
>on the context what actual accesses occur; maybe it's a read, a write,
>both a read and a write, or neither.
It is called an lvalue by the C standard. The current C standard defines
lvalue as "an expression (with an object type or incomplete type other
than void) that designates an object."
>As others have noted, saying that the operator *by itself* generates
>some actual access leads to some strange conclusions. If "*p" by itself
>is an access, is it a read or a write? If it generates a write, that's
>mighty peculiar. If it generates a read, that's also a bit weird.
Non-array lvalues in C are converted to the value stored in the object
"except when it is the operand of the sizeof operator, the unary &
operator, the ++ operator, the -- operator, or the left hand operand of
the . operator or an assignment operator."
You can interpret "converted to the value" as indicating a read access.
Interesting cases are
*p;
(void)*p;
both of which generate a read access side-effect if p points to a
volatile object (because they aren't one of the exceptions listed above).
>If we say "*p = 0;", does the "*p" do a read,
No, it is one of the exceptions.
>then the assignment do a write? Or is there no write?
There is just a write side-effect.
>And if we say "x = *p;", does the "*p" do
>a read, then the assignment do another read?
The value of *p is read, converted to the type of x and written to x.
> And if we say "*p += x;"
>does the "*p" do a read, then the assignment do another read and a
>write? Should we have read-read-modify-write instructions for this?
This is defined to be a simple read-modify-write of *p.
A more interesting case is
y = *p = x;
Here you have to decide whether there is an explicit read side-effect of *p
or whether the value assigned to *p is simply held as the result of (*p = x).
I interpret the C standard as saying that there is a separate read
side-effect, so with the I/O example above the value of x is written to the
"write register" and y is then assigned the subsequent value of the
"read register", i.e. it is equivalent to
*p = x, y = *p;
--
-----------------------------------------
Lawrence Kirby | fred@genesis.demon.co.uk
Wilts, England | 70734.126@compuserve.com
-----------------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/10/14 Raw View
Lawrence Kirby wrote:
>
> Paul D. DeRocco <pderocco@ix.netcom.com> writes:
> >&*z seems like a C/C++ equivalent to LEA.
>
> LEA corresponds to plain &, not &*.
If you use a register as a pointer, as in
MOV EAX, [EBX]
you're doing the equivalent of "*", but when you do
LEA EAX, [EBX]
you're doing the equivalent of "&*". That's all I meant.
--
Ciao,
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Joe Keane <jgk@jgk.org>
Date: 1998/10/15 Raw View
In article <F0MLDC.1M4@research.att.com>
Andrew Koenig <ark@research.att.com> writes:
>Consider:
>
> int& set(int& x, int y)
> {
> x = y;
> return x;
> }
>
>Looking at this function, many programmers will be tempted to rewrite it as
>
> int& set(int& x, int y)
> {
> return x = y;
> }
That code is dumb.
Despite the facile syntax, it's not returning a value. The function
returns a reference, to be more explicit, it's passing back the caller
a pointer to some location that it can modify.
I don't know why someone would think that "x = y" should be a location
that you can modify. It looks like an assignment operation to me.
But maybe i'm missing the subtlety of the great C++.
You know, this is exactly the sort of thing that makes C++ next to
impossible to use. It's all the little goodies that do cute little
tricks for you automatically, instead of asking you to type a few
characters to make clear what you want.
Meanwhile the poor, typical C++ programmer has no clue why his code
calls some function. In C, this is laughable. But in C++, it happens
all the time. It would be great if the magic always did the right
thing, but somehow it always seems to come up a bit short.
Let's try the same thing in C. Note that we have to write actual
operators to do things, so it takes a couple more characters.
int *set(int *xp, int y)
{
return &(*xp = y);
}
Hmm, that doesn't work. Why don't you see people screaming about some
deficiency in the language? Maybe it looks like a dumb thing to do?
What's the address of an assignment? It's not too clear, is it?
However, if you want to return xp, you can say "return xp;".
Let's try a different operator:
int *equals(int x, int y)
{
return &(x == y);
}
That doesn't work either.
int *plus(int x, int y)
{
return &(x + y);
}
No, that doesn't work either.
int *xor(int x, int y)
{
return &(x ^ y);
}
Same thing, it doesn't work.
Now for something completely different:
int *index(int *xp, int y)
{
return &xp[y];
}
Ooh, that works! Maybe it makes sense and it does something useful?
--
Joe Keane, amateur mathematician
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/10/15 Raw View
In article <702lsf$bqn$1@rocky.jgk.org>, Joe Keane <jgk@jgk.org> wrote:
> That code is dumb.
...which is just an impolite way of saying that you don't like it.
And it develops from your later examples that the reason you don't
like it is that you don't like references at all.
So the argument boils down to this:
You say that you think it's a bad idea for assignment in
C++ to return an lvalue.
I say that doing so is a logical consequence of introducing
references into the language.
You respond by saying that the language shouldn't have
references.
If I point out that references are essential for operator
overloading (to allow expressions such as cin >> x instead
of requiring cin >> &x), I imagine you will say that there
is no need for operator overloading.
In which case there isn't really much else to talk about. It is always
possible to eliminate things, and eventually you wind up with nothing.
``The Sage needs nothing, not even life.'' --Raymond Smullyan
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: zalman@netcom.com (Zalman Stern)
Date: 1998/10/15 Raw View
Andrew Koenig (ark@research.att.com) wrote:
: In article <702lsf$bqn$1@rocky.jgk.org>, Joe Keane <jgk@jgk.org> wrote:
: > That code is dumb.
: ...which is just an impolite way of saying that you don't like it.
I shall try to convince you that there is a point here. Just to reiterate,
here's the code:
> int& set(int& x, int y)
> {
> return x = y;
> }
I have a problem with the above in that the standard says the result of an
assignment operator "...is the value stored in the left operand after the
assignment has taken place; the result is an lvalue." I do not believe the
standard says or implies that "x = y" returns a reference to x . In fact I
got into an argument with a compiler vendor about this and they said the
assignment statement may return a reference to a temporary location (even
if no temporary was created by the assignment). Discussion in this
newsgroup and comp.lang.c++ did not reach a direct conclusion and I still
see this as unclear. (Though I think it is obvious that a reference to the
exact object assigned to should *always* be returned unless a (broken)
overloaded assignment operator is involved. I wish the standard said that
or made it clear that I'm wrong.)
With overloaded assignment operators, one is at the mercy of whatever
reference the operator decides to return. Hence one can make the case that
changing the above to return the reference explicitly is an iota or two
more robust.
-Z-
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/10/05 Raw View
In article <3610065D.5ED2@sig.please>, Chris Kuan <look@sig.please> wrote:
> > It provides no benefit at all, but that's the way the rules are anyway.
> > I don't like them any more than you do, but disliking them doesn't change them.
> But changing them does :-)
> What I mean is:
> (From the draft C standard)
> [#3] The result of the unary & (address-of) operator is a
> pointer to the object or function designated by its operand.
> If the operand has type ``type'', the result has type
> ``pointer to type''. If the operand is the result of a
> unary * operator, neither that operator nor the & operator
> is evaluated, and the result is as if both were omitted,
> except that the constraints on the operators still apply and
> the result is not an lvalue. Similarly, if the operand is
> the result of a [] operator, neither the & operator nor the
> unary * that is implied by the [] is evaluated, and the
> result is as if the & operator were removed and the []
> operator were changed to a + operator.
> Could this be adopted for C++2003?
In principle -- but is it correct? It says that "the constraints on the
operators still apply." Do the constraints include the one that says
that the operand of * must be a valid address?
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: zalman@netcom.com (Zalman Stern)
Date: 1998/10/05 Raw View
Paul D. DeRocco (pderocco@ix.netcom.com) wrote:
: Zalman Stern wrote:
: > int *nul = &*(int *)NULL;
: Why is it necessary that the "int *nul" one be made illegal?
It is already undefined. I am saying this should not be changed.
: For instance, there's
: no reason to expect the compiler to complain about the last line of:
: int tri[3];
: int* foo = tri + 3;
: int& bar = *foo;
: or for that matter:
: int* foo = NULL;
: int& bar = *foo;
: These are run-time errors, and beyond the scope of what a compiler
: should be expected to catch, especially if you put more "distance"
: between the lines, such as by putting one in a function and the other in
: its caller.
Who said anything about compile time errors? We said the code is undefined.
Which means I have the right to tell people not to write code that does the
above because it is an error. Whether the compiler catches it or not. There
are tools that will flags an error on both of the above constructs. And I
believe those tools should be allowed to do so.
Language standards are not determined by what you can get away with given
some (or even most) compilers (today).
-Z-
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/10/06 Raw View
In article <christian.bau-0210981808400001@christian-mac.isltd.insignia.com>,
christian.bau@isltd.insignia.com (Christian Bau) wrote:
> In article <6v0vq5$ulh$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
>
> > So we have:
> >
> > int nv; // Not-volatile
> > volatile int v; // Volatile
> <skipped some examples>
> > v;
> > // Again, no operators, so no side effects. I think that a
> > // compiler is justified in optimizing this away, even though
> > // it is declared volatile.
>
> Isnt this example one of the subtle differences between C and C++? I think
> there is slightly different wording that makes this an access to v in C,
> but not in C++.
Why do you say so? Can you quote relevant passages?
> Minor point: IF the compiler is "justified in optimizing
> this away", then I think it is REQUIRED to optimize it away.
What makes you say this? Where in the standard are any
optimizations required?
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/10/06 Raw View
In article <m34stm11k2.fsf@gabi-soft.fr>,
kanze@gabi-soft.fr (J. Kanze) wrote:
> AllanW@my-dejanews.com writes:
>
> |> I believe it does the "dereference" in connection with passing
> |> operands to operators. The operators have the side effects.
>
> The problem is more subtle than you think.
Probably so. I'm not an expert, but I have found my intuition to be
a good (though not perfect) guide, probably because the standards
committee tried very hard to make the language intuitive and
unsurprising (and succeeded, to a degree, although there are certainly
"dark corners" of the language...)
> |> So we have:
> |>
> |> int nv; // Not-volatile
> |> volatile int v; // Volatile
> |>
> |> nv = 0;
> |> // The compiler must logically change the value of nv. But
> |> // it isn't required to actually write 0 into any particular
> |> // RAM address; so long as the as-if rule is followed, the
> |> // compiler may be able to optimize it to nothing.
> |>
> |> nv = 0;
> |> // In particular, most "optimizing" compilers will make
> |> // this statement a no-op, since nv already has the correct
> |> // value.
> |>
> |> v = 0;
> |> // Not so in this case. If we find the correct RAM address for
> |> // v (which, ironically, is implementation-defined), and we
> |> // are able to observe all activity to that address, then we
> |> // must be able to observe the compiler writing a 0 to that
> |> // address for this instruction.
>
> This statement has a result, the value just written to v.
Clearly. The result must be 0.
> At least one
> person has argued (in C) that this value is a result of reading v after
> the write, and the a conforming compiler must generate both a write and
> a read of v.
Just because the value is 0 doesn't mean that the result came from v.
One could argue that the value written into v is also the result,
which certainly doesn't imply re-reading it from v!
> This is, of course, a useless interpretation, and one that is not
> implemented by any compiler I've ever heard of. On the other hand, I
> think that the C standards committee (or at least, the members of it
> that participated in the discussion in comp.std.c) felt that no
> clarification was needed. Since the meaning of an "access" is
> implementation defined, it is really up to the implementation to decide
> what it wants to do. All real implementations will choose a useful
> interpretation for their hardware.
Does the standard even state that v is accessed in this case? I wasn't
able to find it.
> Note that the response becomes less evident if I write nv = (v =
> 0). And v is actually an expression which designates an external memory
> mapped port, where reading fetches something totally different from what
> was written. The exact words for = in the C standard are "An assignment
> expression has the value of the left operand after the assignment." So
> one would expect the above expression to mean exactly the same as:
> v = 0 ;
> nv = v ;
I wouldn't expect this. Or, rather, I would expect that
temp = 0;
v = temp;
nv = temp;
was just as valid.
I know that the result of
float d;
d = nv;
is a floating-point 0 (as opposed to the int 0 that we started with).
But I don't think that this implies reading it from d!
> In this case, this effect can only be achieved by actually reading v.
> (I'm not talking here about the number of accesses, but the value of
> nv. In the second case, I don't think that there is the slightest doubt
> that two accesses are required, because of the intervening sequence
> point.)
True if (and only if) nv must get v's value, as opposed to the value
written into v.
> |> v = 0;
> |> // And again, the compiler isn't allowed to optimize it away --
> |> // it must store 0 in the variable, even though it may look as
> |> // if the variable already holds that value.
> |>
> |> nv = v;
> |> // Here, we must read the value from v and use that as the new
> |> // value for nv. Nothing says we must actually write it to nv's
> |> // prior memory location, but certainly we must read v's value
> |> // from RAM, rather than assuming it's still 0.
>
> Correct. Which is what leads to the problem above.
Again, depending on weather we actually have to read v in that case.
> |> v = nv;
> |> // And once again, we can get the value for nv any way we like,
> |> // but we must literally write into v's memory location.
> |>
> |> nv;
> |> // A compiler doesn't have to be terribly good at optimizing to
> |> // be able to send this whole statement to the bit bucket. But
> |> // consider what happens before optimization. This is a variable
> |> // name, which is an l-value. There is no operator here, so there
> |> // is no side-effect. Why are l-values statements? It has to be
> |> // because l-values can be converted to r-values; recall that
> |> // r-values are explicitly listed as valid expressions, and thus
> |> // valid statements. Does the process of converting the l-value
> |> // into an r-value require the data to be read?
> |>
> |> v;
> |> // Again, no operators, so no side effects. I think that a
> |> // compiler is justified in optimizing this away, even though
> |> // it is declared volatile.
>
> This is the question.
Agreed. The statement is an expression-statement; the expression is
evaluated and its value is discarded [CD2 6.2 #1]. The expression is
an assignment-expression; specifically, a conditional-expression;
specifically, a logical-or-expression; ... and so on until we get to
anb id-expression, specifically an unqualified-id, specifically an
identifier.
None of these references state that the value is to be "read" or
"accessed" in any way; they state only what the "value" of the
expression is.
> I think a formal reading of the (C) standard would say no; the
> expression has a value, even if it is not used.
The standard clearly states that the expression has a value, and
that the value is "discarded." Does that mean that RAM (or other
I/O at that address) must be activated?
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Chris Kuan <look@sig.please>
Date: 1998/10/06 Raw View
Andrew Koenig wrote:
>
> In article <3610065D.5ED2@sig.please>, Chris Kuan <look@sig.please> wrote:
>
> > (From the draft C standard)
>
> > [#3] The result of the unary & (address-of) operator is a
> > pointer to the object or function designated by its operand.
> > If the operand has type ``type'', the result has type
> > ``pointer to type''. If the operand is the result of a
> > unary * operator, neither that operator nor the & operator
> > is evaluated, and the result is as if both were omitted,
> > except that the constraints on the operators still apply and
> > the result is not an lvalue. Similarly, if the operand is
> > the result of a [] operator, neither the & operator nor the
> > unary * that is implied by the [] is evaluated, and the
> > result is as if the & operator were removed and the []
> > operator were changed to a + operator.
>
> > Could this be adopted for C++2003?
>
> In principle -- but is it correct? It says that "the constraints on the
> operators still apply." Do the constraints include the one that says
> that the operand of * must be a valid address?
The only constraints that I can find on the operators are:
6.5.3.2 Address and indirection operators
Constraints
[#1] The operand of the unary & operator shall be either a
function designator, the result of a [] or unary * operator,
or an lvalue that designates an object that is not a bit-
field and is not declared with the register storage-class
specifier.
[#2] The operand of the unary * operator shall have pointer
type.
Para. [#3] above follows those two, under "Semantics". Then
follows a para. about the validity of the expression:
[#4] The unary * operator denotes indirection. If the
operand points to a function, the result is a function
designator; if it points to an object, the result is an
lvalue designating the object. If the operand has type
``pointer to type'', the result has type ``type''. If an
invalid value has been assigned to the pointer, the behavior
of the unary * operator is undefined.72)
Footnote 72 reads thus:
72)Thus, &*E is equivalent to E (even if E is a null
pointer), and &(E1[E2]) to ((E1)+(E2)). It is always
true that if E is a function designator or an lvalue that
is a valid operand of the unary & operator, *&E is a
function designator or an lvalue equal to E. If *P is an
lvalue and T is the name of an object pointer type, *(T)P
is an lvalue that has a type compatible with that to
which T points.
Among the invalid values for dereferencing a pointer by
the unary * operator are a null pointer, an address
inappropriately aligned for the type of object pointed
to, and the address of an automatic storage duration
object when execution of the block with which the object
is associated has terminated.
Putting all that together, I think the intent is that even if
T contains an invalid address, &*T is supposed to be well-defined.
On the other hand, I'm still having trouble understanding the
behaviour in the presence of (C++) user-defined operators, so I'm
not claiming any One Great Truth here.
--
Chris Kuan, BHP Information Technology
Concatenate for email: mr gazpacho @ hotmail . com
Phone : +61 2 4275 5555 Fax : +61 2 4275 5547
"A Design Pattern is something that got left out of the language"
- Richard O'Keefe
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Joe Keane <jgk@jgk.org>
Date: 1998/10/06 Raw View
In article <36119ED3.C6864ABA@ix.netcom.com>
Paul D. DeRocco <pderocco@ix.netcom.com> writes:
>But what does it mean to "dereference" a pointer, really? It can mean
>either to read through it or to write through it, and nothing else. But
>one of the purposes of the volatile keyword is to allow C/C++ to access
>memory-mapped I/O ports. In this case, reading *z may access a
>completely different register from writing *z. So which register should
>&*z access? Obviously, it can't write *z, because it doesn't know what
>to write. But why should it read *z, either, since it doesn't need the
>value? Intuitively, I wouldn't expect &*z either to read _or_ write. But
>perhaps that's just a perception borne of twenty years of assembly
>language programming. For instance, the x86 LEA instruction doesn't
>complain if its operand refers to un-mapped memory, and &*z seems like a
>C/C++ equivalent to LEA.
That's my understanding.
I tend to think that people have a misunderstanding of C here, but it's
certainly a subtle point so i don't think people are dumb or anything.
I'd say, by itself, a star operator, or arrow or brackets, creates a
memory *operand*, that is, a potential memory access. Then it depends
on the context what actual accesses occur; maybe it's a read, a write,
both a read and a write, or neither.
As others have noted, saying that the operator *by itself* generates
some actual access leads to some strange conclusions. If "*p" by itself
is an access, is it a read or a write? If it generates a write, that's
mighty peculiar. If it generates a read, that's also a bit weird.
If we say "*p = 0;", does the "*p" do a read, then the assignment do a
write? Or is there no write? And if we say "x = *p;", does the "*p" do
a read, then the assignment do another read? And if we say "*p += x;"
does the "*p" do a read, then the assignment do another read and a
write? Should we have read-read-modify-write instructions for this?
Well no, these are silly, but it's consistent with the reasoning.
--
Joe Keane, amateur mathematician
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: 1998/10/07 Raw View
AllanW@my-dejanews.com wrote:
: In article <m34stm11k2.fsf@gabi-soft.fr>,
: kanze@gabi-soft.fr (J. Kanze) wrote:
: > AllanW@my-dejanews.com writes:
: >
James has been quoting the C standard while Allan has been quoting
CD2. I must be confused since my understanding is that opposite
standards would support the views. Cutting to the example below:
nv = (v = 0);
: > Note that the response becomes less evident if I write nv = (v =
: > 0). And v is actually an expression which designates an external memory
: > mapped port, where reading fetches something totally different from what
: > was written. The exact words for = in the C standard are "An assignment
: > expression has the value of the left operand after the assignment." So
: > one would expect the above expression to mean exactly the same as:
: > v = 0 ;
: > nv = v ;
The value of = in C is an rvalue; so, I would expect it to be the
value written to the left operand. The left operand was used for a
write not a read. The two forms may not be the same.
: I wouldn't expect this. Or, rather, I would expect that
: temp = 0;
: v = temp;
: nv = temp;
: was just as valid.
The value of = in C++ is an lvalue; so, I would expect it to be the
left operand. Now an lvalue to rvalue conversion is required which is
an access. The two forms may well be the same and not at all the same
as this one.
If access is implementation defined, then the standards do not specify
what happens in either language.
Going back to the original:
v;
Is that an lvalue or rvalue expression? In which language?
Any deconfusion available?
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: markw65@my-dejanews.com
Date: 1998/10/07 Raw View
In article <6vc9lm$cmk$1@nnrp1.dejanews.com>,
AllanW@my-dejanews.com wrote:
> In article <m34stm11k2.fsf@gabi-soft.fr>,
> kanze@gabi-soft.fr (J. Kanze) wrote:
[nv is a non-volatile variable, v is a volatile variable]
>
> > Note that the response becomes less evident if I write nv = (v =
> > 0). And v is actually an expression which designates an external memory
> > mapped port, where reading fetches something totally different from what
> > was written. The exact words for = in the C standard are "An assignment
> > expression has the value of the left operand after the assignment." So
> > one would expect the above expression to mean exactly the same as:
> > v = 0 ;
> > nv = v ;
>
> I wouldn't expect this. Or, rather, I would expect that
> temp = 0;
> v = temp;
> nv = temp;
> was just as valid.
>
Except that the result of the assignment is an lvalue. Specifically the lhs of
the assignment, ie v. So the result must be read from v.
Mark Williams
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 1998/10/08 Raw View
In article <6vc9om$cn8$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
> In article <christian.bau-0210981808400001@christian-mac.isltd.insignia.com>,
> christian.bau@isltd.insignia.com (Christian Bau) wrote:
> > In article <6v0vq5$ulh$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
> >
> > > So we have:
> > >
> > > int nv; // Not-volatile
> > > volatile int v; // Volatile
> > <skipped some examples>
> > > v;
> > > // Again, no operators, so no side effects. I think that a
> > > // compiler is justified in optimizing this away, even though
> > > // it is declared volatile.
> >
> > Isnt this example one of the subtle differences between C and C++? I think
> > there is slightly different wording that makes this an access to v in C,
> > but not in C++.
>
> Why do you say so? Can you quote relevant passages?
I say so because there was a thread on comp.std.c about exactly this, and
how after a declaration of
volatile int* p;
the statement
"*p;"
in C is an "access" to *p, but for some reason the rules in C++ are a bit
different, and *p on its own is no "access". So if your intention is to
have a read access to some memory mapped hardware, you better write "(int)
*p;" instead of "*p;". I think the rules when lvalues become rvalues are a
bit different in C and C++, probably because of references.
> > Minor point: IF the compiler is "justified in optimizing
> > this away", then I think it is REQUIRED to optimize it away.
>
> What makes you say this? Where in the standard are any
> optimizations required?
We are talking about volatile objects. The compiler NEVER has a choice
whether to access a volatile object or not. An access to a volatile object
either MUST happen or MUST NOT happen. So if a compiler is "justified to
optimise an access to a volatile object away", then obviously not
accessing the object is legal, and therefore accessing it is illegal.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/10/08 Raw View
> nv = (v = 0);
kanze@gabi-soft.fr (J. Kanze) wrote:
> : > one would expect the above expression to mean exactly the same as:
> : > v = 0 ;
> : > nv = v ;
AllanW@my-dejanews.com wrote:
> : I wouldn't expect this. Or, rather, I would expect that
> : temp = 0;
> : v = temp;
> : nv = temp;
> : was just as valid.
jpotter@falcon.lhup.edu (John Potter) wrote:
> The value of = in C++ is an lvalue; so, I would expect it to be the
> left operand. Now an lvalue to rvalue conversion is required which is
> an access. The two forms may well be the same and not at all the same
> as this one.
I've just spent two hours trying to write a clear and yet extremely
detailed account of why my interpretation was the only correct one.
I failed! I am now absolutely convinced that if operator= returns
an lvalue, then
nv = (v = 0);
must write into v, and then re-read the value back out again -- just
as James spelled out above. Perhaps what I wrote above would work in
C, I don't know any more.
May I please ask someone on the C++ standardization committee to explain
WHY the result of operator= is an lvalue? Are we trying to support code
such as
((v = 3) = 5) = 7;
which now seems to be legal, and even works on my compiler? What's the
point of this?
> Going back to the original:
>
> v;
>
> Is that an lvalue or rvalue expression? In which language?
I am still convinced that this is an lvalue expression in either
language (C or C++). (Remember that lvalues can be converted into
rvalues, so really the answer is "both".) But the question was,
does this require an access to v's value? If so, is it a read
access or a writeaccess -- and if it's a write access, what is
written?
I still feel that this should be a no-op, even if v is volatile,
but I'm no longer as certain as I once was...
> Any deconfusion available?
Please...
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: markw65@my-dejanews.com
Date: 1998/10/08 Raw View
In article <6vg6qb$s28$1@nnrp1.dejanews.com>,
AllanW@my-dejanews.com wrote:
> > nv = (v = 0);
> kanze@gabi-soft.fr (J. Kanze) wrote:
> > : > one would expect the above expression to mean exactly the same as:
> > : > v = 0 ;
> > : > nv = v ;
> AllanW@my-dejanews.com wrote:
> > : I wouldn't expect this. Or, rather, I would expect that
> > : temp = 0;
> > : v = temp;
> > : nv = temp;
> > : was just as valid.
> jpotter@falcon.lhup.edu (John Potter) wrote:
> > The value of = in C++ is an lvalue; so, I would expect it to be the
> > left operand. Now an lvalue to rvalue conversion is required which is
> > an access. The two forms may well be the same and not at all the same
> > as this one.
> I've just spent two hours trying to write a clear and yet extremely
> detailed account of why my interpretation was the only correct one.
>
> I failed! I am now absolutely convinced that if operator= returns
> an lvalue, then
> nv = (v = 0);
> must write into v, and then re-read the value back out again -- just
> as James spelled out above. Perhaps what I wrote above would work in
> C, I don't know any more.
In C++ the result of the assignment _is_ an lvalue, but its type is the
*unqualified* type of the lhs (at least for builtin types, and for class
types it all depends on the assignment operator). So presumably although the
abstract machine is required to re-read the value from v, a real
implementation is allowed to optimize the read away, and use the stored
value, ie zero in this case.
In C the assignment has the value of the left operand after assignment, but is
not an lvalue. It also has the unqualified type of the left operand. So again,
the read can be optimized away, even when the lhs is volatile.
> May I please ask someone on the C++ standardization committee to explain
> WHY the result of operator= is an lvalue? Are we trying to support code
> such as
> ((v = 3) = 5) = 7;
> which now seems to be legal, and even works on my compiler? What's the
> point of this?
>
> > Going back to the original:
> >
> > v;
> >
> > Is that an lvalue or rvalue expression? In which language?
> I am still convinced that this is an lvalue expression in either
> language (C or C++). (Remember that lvalues can be converted into
> rvalues, so really the answer is "both".) But the question was,
> does this require an access to v's value? If so, is it a read
> access or a writeaccess -- and if it's a write access, what is
> written?
> I still feel that this should be a no-op, even if v is volatile,
> but I'm no longer as certain as I once was...
> > Any deconfusion available?
> Please...
An lvalue (except as the operand of one of a small set of operators) is
converted to the value stored in it. ie, in the abstract machine, it is read.
Since v is volatile, its value must be read.
Mark Williams
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 1998/10/08 Raw View
In article <6vg6qb$s28$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
> May I please ask someone on the C++ standardization committee to explain
> WHY the result of operator= is an lvalue? Are we trying to support code
> such as
> ((v = 3) = 5) = 7;
> which now seems to be legal, and even works on my compiler? What's the
> point of this?
To make the following legal:
void f (int& x);
int i;
f (i = 3);
f (++i);
((v = 3) = 5) = 7;
obviously gives you undefined behavior (v is modified three times with
no sequence point in sight).
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: William Roeder <roeder@dba-sys.com>
Date: 1998/10/08 Raw View
AllanW@my-dejanews.com wrote:
>
<snip>
>
> The standard clearly states that the expression has a value, and
> that the value is "discarded." Does that mean that RAM (or other
> I/O at that address) must be activated?
>
If you consider volatile int *p where p points to a hardware register
(serial port for example)
*p = outchr;
char inchr = *p;
Obviously an access to memory is required and the compiler can not
assume that outchr == inchr.
Volatile means that the memory can change outside the knowledge of the
compiler.
begin: vcard
fn: William Roeder
n: Roeder;William
org: DBA Systems Inc.
email;internet: roeder@dba-sys.com
title: Sr. Staff Scientist
x-mozilla-cpt: ;0
x-mozilla-html: TRUE
version: 2.1
end: vcard
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/10/09 Raw View
Christian Bau wrote:
> In article <6vc9om$cn8$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
> > In article <christian.bau-0210981808400001@christian-mac.isltd.insignia.com>,
> > christian.bau@isltd.insignia.com (Christian Bau) wrote:
> > > Minor point: IF the compiler is "justified in optimizing
> > > this away", then I think it is REQUIRED to optimize it away.
> > What makes you say this? Where in the standard are any
> > optimizations required?
> We are talking about volatile objects. The compiler NEVER has a choice
> whether to access a volatile object or not. An access to a volatile object
> either MUST happen or MUST NOT happen.
Again, where does the standard says that ?
--
Valentin Bonnard mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/10/09 Raw View
Christian Bau wrote:
[...]
> I say so because there was a thread on comp.std.c about exactly this, and
> how after a declaration of
>
> volatile int* p;
>
> the statement
>
> "*p;"
>
> in C is an "access" to *p, but for some reason the rules in C++ are a bit
> different, and *p on its own is no "access". So if your intention is to
> have a read access to some memory mapped hardware, you better write "(int)
> *p;" instead of "*p;". I think the rules when lvalues become rvalues are a
> bit different in C and C++, probably because of references.
Does &*p constitute an access in C++?
If not so, but lvalue to rvalue conversion is, then the
"invalid lvalue" rule I've suggested in another posting is quite
simple to state:
Dereferencing a one-past-end pointer is well defined and yields an
invalid lvalue. Accessing an invalid lvalue is undefined behaviour.
This would make the big quoted text of the C9x draft superfluous
in C++, since it already allows &*p on a one-past-the-end pointer,
and also would give a more general rule: As long as you don't
access that lvalue, you can do everything you want with it (which
obviously reduces to "not very much", since almost everything is
an access ;-))
If one does not like the specific "one-past-the-end" in the rule,
one could alternatively define:
Dereferecing a valid pointer not pointing to a valid object
is well defined and yields an invalid lvalue. Accessing an
invalid lvalue is undefined behaviour.
This would indeed widen the definition a little bit, since
a null pointer is a valid pointer not pointing to a valid
object as well. However, in the quoted C9x draft section,
&*NULL was allowed, too.
[...]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/10/09 Raw View
William Roeder wrote:
> AllanW@my-dejanews.com wrote:
> >
> > The standard clearly states that the expression has a value, and
> > that the value is "discarded." Does that mean that RAM (or other
> > I/O at that address) must be activated?
> >
> If you consider volatile int *p where p points to a hardware register
> (serial port for example)
> *p = outchr;
> char inchr = *p;
> Obviously an access to memory is required and the compiler can not
> assume that outchr == inchr.
>
> Volatile means that the memory can change outside the knowledge of the
> compiler.
However, the question is if
v;
must by itself cause a read, if v is volatile.
This can be important, if v references a port where data is held
in a (HW-)queue. Say, at the beginning this queue contains
1 2 3
(read from left), and the code is:
v; result=v;
then if v; triggers a read access, you'll get result=2 and the queue
contains 3 only (and new data, if any). Otherwise, result=1 and the
queue contains 2 3 <possibly new data>. Quite different behaviour.
BTW, a similar question arises for
v, result=v;
Is the left operand of the comma operator accessed?
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: zalman@netcom.com (Zalman Stern)
Date: 1998/10/02 Raw View
Andrew Koenig (ark@research.att.com) wrote:
: It provides no benefit at all, but that's the way the rules are anyway.
: I don't like them any more than you do, but disliking them doesn't change them.
[Quoting Andrew because he has made clear what the standard says and that
the committee had trouble coming up with rules that "fixed" this. I am not
sure there is anything to fix and offer the following illustration.]
int tri[3];
int *belzhi = &tri[3];
int &chornyi = tri[3];
int *nul = &*(int *)NULL;
int &smert = *(int *)NULL;
Any rule that makes the first assignment legal, must still outlaw the other
three. For those thinking "Well its just a bunch of asignments, what harm
can it do?" then take this scenario:
void pochemu(int *, int &, int *, int &) {};
int tri[3];
pochemu(&tri[3], tri[3], &*(int *)NULL, *(int *)NULL);
(I've had major arguments with people who feel it is ok to cast into
existence undefined references. I believe the standard is squarely against
them and hope it remains that way.)
It is a flawed perspective that taking a pointer to one beyond the end of a
three element array using "&array[3]" is *obviously* an ok thing to do.
-Z-
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 1998/10/03 Raw View
In article <6v0vq5$ulh$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com wrote:
> So we have:
>
> int nv; // Not-volatile
> volatile int v; // Volatile
<skipped some examples>
> v;
> // Again, no operators, so no side effects. I think that a
> // compiler is justified in optimizing this away, even though
> // it is declared volatile.
Isnt this example one of the subtle differences between C and C++? I think
there is slightly different wording that makes this an access to v in C,
but not in C++. Minor point: IF the compiler is "justified in optimizing
this away", then I think it is REQUIRED to optimize it away.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/10/03 Raw View
AllanW@my-dejanews.com writes:
|> I believe it does the "dereference" in connection with passing
|> operands to operators. The operators have the side effects.
The problem is more subtle than you think.
|> So we have:
|>
|> int nv; // Not-volatile
|> volatile int v; // Volatile
|>
|> nv = 0;
|> // The compiler must logically change the value of nv. But
|> // it isn't required to actually write 0 into any particular
|> // RAM address; so long as the as-if rule is followed, the
|> // compiler may be able to optimize it to nothing.
|>
|> nv = 0;
|> // In particular, most "optimizing" compilers will make
|> // this statement a no-op, since nv already has the correct
|> // value.
|>
|> v = 0;
|> // Not so in this case. If we find the correct RAM address for
|> // v (which, ironically, is implementation-defined), and we
|> // are able to observe all activity to that address, then we
|> // must be able to observe the compiler writing a 0 to that
|> // address for this instruction.
This statement has a result, the value just written to v. At least one
person has argued (in C) that this value is a result of reading v after
the write, and the a conforming compiler must generate both a write and
a read of v.
This is, of course, a useless interpretation, and one that is not
implemented by any compiler I've ever heard of. On the other hand, I
think that the C standards committee (or at least, the members of it
that participated in the discussion in comp.std.c) felt that no
clarification was needed. Since the meaning of an "access" is
implementation defined, it is really up to the implementation to decide
what it wants to do. All real implementations will choose a useful
interpretation for their hardware.
Note that the response becomes less evident if I write nv = (v =
0). And v is actually an expression which designates an external memory
mapped port, where reading fetches something totally different from what
was written. The exact words for = in the C standard are "An assignment
expression has the value of the left operand after the assignment." So
one would expect the above expression to mean exactly the same as:
v = 0 ;
nv = v ;
In this case, this effect can only be achieved by actually reading v.
(I'm not talking here about the number of accesses, but the value of
nv. In the second case, I don't think that there is the slightest doubt
that two accesses are required, because of the intervening sequence
point.)
|> v = 0;
|> // And again, the compiler isn't allowed to optimize it away --
|> // it must store 0 in the variable, even though it may look as
|> // if the variable already holds that value.
|>
|> nv = v;
|> // Here, we must read the value from v and use that as the new
|> // value for nv. Nothing says we must actually write it to nv's
|> // prior memory location, but certainly we must read v's value
|> // from RAM, rather than assuming it's still 0.
Correct. Which is what leads to the problem above.
|> v = nv;
|> // And once again, we can get the value for nv any way we like,
|> // but we must literally write into v's memory location.
|>
|> nv;
|> // A compiler doesn't have to be terribly good at optimizing to
|> // be able to send this whole statement to the bit bucket. But
|> // consider what happens before optimization. This is a variable
|> // name, which is an l-value. There is no operator here, so there
|> // is no side-effect. Why are l-values statements? It has to be
|> // because l-values can be converted to r-values; recall that
|> // r-values are explicitly listed as valid expressions, and thus
|> // valid statements. Does the process of converting the l-value
|> // into an r-value require the data to be read?
|>
|> v;
|> // Again, no operators, so no side effects. I think that a
|> // compiler is justified in optimizing this away, even though
|> // it is declared volatile.
This is the question.
I think a formal reading of the (C) standard would say no; the
expression has a value, even if it is not used.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/10/05 Raw View
Zalman Stern wrote:
>
> int tri[3];
>
> int *belzhi = &tri[3];
> int &chornyi = tri[3];
> int *nul = &*(int *)NULL;
> int &smert = *(int *)NULL;
>
> Any rule that makes the first assignment legal, must still outlaw the
> other three.
Why is it necessary that the "int *nul" one be made illegal? I
understand that what we're arguing about is the &* combination, but
you're implying that your example exposes something evil about it,
beyond the fact that it violates the precise wording of the standard. I
also understand that you're pointing out the problem of converting a
pointer-to-one-past-the-end into a reference-to-one-past-the-end, but
that problem exists whether you write &* or not. For instance, there's
no reason to expect the compiler to complain about the last line of:
int tri[3];
int* foo = tri + 3;
int& bar = *foo;
or for that matter:
int* foo = NULL;
int& bar = *foo;
These are run-time errors, and beyond the scope of what a compiler
should be expected to catch, especially if you put more "distance"
between the lines, such as by putting one in a function and the other in
its caller.
--
Ciao,
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/09/30 Raw View
In article <6uqk0l$he$1@nnrp1.dejanews.com>,
jkanze@otelo.ibmmail.com wrote:
> &*z means take the address of the results of dereferencing z.
>
> Formally, z MUST be dereferenced; in fact, of course, unless z is declared
> volatile, dereferencing results in no change in the observable behavior,
> and most compilers will optimize the dereference out of the generated
> code. (If, of course, z is declared volatile, the dereference had better
> take place.)
void volfunc(volatile int&) { /* Empty */ }
int main() {
volatile int volint = 2;
volfunc(volint); // Is this required to cause a reference?
volatile int *volptr = &volint; // or this?
volfunc(*volptr); // or this?
volatile int &volref = volint; // or this?
volfunc(volref); // or this?
}
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/30 Raw View
jkanze@otelo.ibmmail.com wrote:
>
> There is actually a real problem here; try declaring array volatile.
> Should (must) the compiler generate an access at the given address?
No. If it did, what sort of access would it be, a read or a write?
Taking the address of something doesn't "access" it, in the sense of the
word as usually applied to computer memories.
--
Ciao,
Paul
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/30 Raw View
jkanze@otelo.ibmmail.com wrote:
>
> &*z means take the address of the results of dereferencing z.
>
> Formally, z MUST be dereferenced; in fact, of course, unless z is
> declared volatile, dereferencing results in no change in the
> observable behavior, and most compilers will optimize the dereference
> out of the generated code. (If, of course, z is declared volatile,
> the dereference had better take place.)
But what does it mean to "dereference" a pointer, really? It can mean
either to read through it or to write through it, and nothing else. But
one of the purposes of the volatile keyword is to allow C/C++ to access
memory-mapped I/O ports. In this case, reading *z may access a
completely different register from writing *z. So which register should
&*z access? Obviously, it can't write *z, because it doesn't know what
to write. But why should it read *z, either, since it doesn't need the
value? Intuitively, I wouldn't expect &*z either to read _or_ write. But
perhaps that's just a perception borne of twenty years of assembly
language programming. For instance, the x86 LEA instruction doesn't
complain if its operand refers to un-mapped memory, and &*z seems like a
C/C++ equivalent to LEA.
--
Ciao,
Paul
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/09/30 Raw View
In article <q4NfS0Ag+LE2Ew2u@robinton.demon.co.uk>,
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> In article <6up373$caq$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
> writes
> >> > The C++ standards committee considered relaxing the rules to permit
> >> > &array[3], but its members could not come up with a way of expressing
> >> > the relaxed rule that they found convincing.
> >
> >Where is the rule, the one they left alone?
>
> Implicit, at least by one interpretation, (I think) in C89 which is why
> C90 has now provided explicit support for such as &array[3]. You can be
> sure they would not have wasted time drafting text if there was no need
> to do so.
Not really so implicit. I don't have my copy of the C standard here to
verify, but I think it states explicitly that in an expression *p, p must
point to a valid object. The C++ standard does this a little more
indirectly, but the text is there: from 5.3.1 "the result [of operator*]
is an lvalue referring to the object or function to which the expression
points." While it doesn't explicitly say that the expression must point
to a valid object, in 3.10, it says: "An lvalue refers to an object or
function." I suppose one could argue about it, but the intent seems clear:
in *p, the result is an lvalue, and an lvalue must refer to an object; as
there is no object at the address array+3, the expression *(array+3)
has no definition, and thus must be invalide.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient=E9e objet --
-- Beratung in objektorientierter Datenverarbeitung
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/30 Raw View
AllanW@my-dejanews.com wrote:
>
> In article <3610065D.5ED2@sig.please>,
> look@sig.please wrote:
> > (From the draft C standard)
> >
> > Committee Draft -- August 3, 1998 WG14/N843
> >
> > 6.5.3.2 Address and indirection operators
> >
> > Semantics
> >
> > [#3] The result of the unary & (address-of) operator is a
> > pointer to the object or function designated by its operand.
> > If the operand has type ``type'', the result has type
> > ``pointer to type''. If the operand is the result of a
> > unary * operator, neither that operator nor the & operator
> > is evaluated, and the result is as if both were omitted,
> > except that the constraints on the operators still apply and
> > the result is not an lvalue. Similarly, if the operand is
> > the result of a [] operator, neither the & operator nor the
> > unary * that is implied by the [] is evaluated, and the
> > result is as if the & operator were removed and the []
> > operator were changed to a + operator.
> >
> > Could this be adopted for C++2003?
>
> And, for more immediate concerns: Given that the standard is now
> "frozen", is there at least some non-normative way to tell vendors
> that this would be a good idea now, even though it isn't required?
I think that most vendors already comply with this; the current
'undefined behavior' on most implementations is usually exactly the C9X
defined behavior.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/10/01 Raw View
In article <$IVaeuADtLE2EwXc@robinton.demon.co.uk>,
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> In article <3610065D.5ED2@sig.please>, Chris Kuan <look@sig.please>
> writes
> >Could this be adopted for C++2003?
>
> Well I doubt if it could as is because the C++ wording would be made
> more complicated by the existence of user-defined operators.
In the C standard, the text is in the equivalent of chapter 5. And the
second paragraph in chapter 5 very clearly states to what degree the
chapter applies to user-defined operators. Some clarification might
be necessary to make it clear that the special case only applies when
neither of the operators involved is overloaded, but all in all, it
shouldn't be that hard.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient=E9e objet --
-- Beratung in objektorientierter Datenverarbeitung
-----=3D=3D Posted via Deja News, The Leader in Internet Discussion =3D=3D=
-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/10/01 Raw View
In article <6urtmo$j47$1@nnrp1.dejanews.com>,
AllanW@my-dejanews.com wrote:
>
> In article <6uqk0l$he$1@nnrp1.dejanews.com>,
> jkanze@otelo.ibmmail.com wrote:
> > &*z means take the address of the results of dereferencing z.
> >
> > Formally, z MUST be dereferenced; in fact, of course, unless z is declared
> > volatile, dereferencing results in no change in the observable behavior,
> > and most compilers will optimize the dereference out of the generated
> > code. (If, of course, z is declared volatile, the dereference had better
> > take place.)
>
> void volfunc(volatile int&) { /* Empty */ }
> int main() {
> volatile int volint = 2;
> volfunc(volint); // Is this required to cause a reference?
>
> volatile int *volptr = &volint; // or this?
> volfunc(*volptr); // or this?
>
> volatile int &volref = volint; // or this?
> volfunc(volref); // or this?
> }
Accessing a volatile variable is an "observable behavior", so all of the
above should cause the variable to be accessed. On the other hand, what
constitues an access is implementation defined.
To tell the truth, this has always been an unclear point, even in the C
standard. Given an expression x=y, the expression has a result, which
is, in the abstract machine, the results of reading the value just written
to x. Does an implementation have to generate a read of x immediately
after writing it? (None do, of course, and doing so would be both counter-
intuitive, and make volatile unusable for at least one of its frequent
uses.)
My only point was that the abstract machine, at least in C, does do some
sort of "dereference", which is what makes the expression undefined.
(The wording in C++ is more complex, and I'm no longer sure about what
it means. For that matter, I'm not even 100% sure that assigning through
a null pointer is illegal, although I'm sure that the intend is that it be.)
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/10/01 Raw View
In article <6utrd6$v0u$1@nnrp1.dejanews.com>,
jkanze@otelo.ibmmail.com wrote:
> In article <6urtmo$j47$1@nnrp1.dejanews.com>,
> AllanW@my-dejanews.com wrote:
> >
> > In article <6uqk0l$he$1@nnrp1.dejanews.com>,
> > jkanze@otelo.ibmmail.com wrote:
> > > &*z means take the address of the results of dereferencing z.
> > >
> > > Formally, z MUST be dereferenced; in fact, of course, unless z is declared
> > > volatile, dereferencing results in no change in the observable behavior,
> > > and most compilers will optimize the dereference out of the generated
> > > code. (If, of course, z is declared volatile, the dereference had better
> > > take place.)
> >
> > void volfunc(volatile int&) { /* Empty */ }
> > int main() {
> > volatile int volint = 2;
> > volfunc(volint); // Is this required to cause a reference?
> >
> > volatile int *volptr = &volint; // or this?
> > volfunc(*volptr); // or this?
> >
> > volatile int &volref = volint; // or this?
> > volfunc(volref); // or this?
> > }
>
> Accessing a volatile variable is an "observable behavior", so all of the
> above should cause the variable to be accessed. On the other hand, what
> constitues an access is implementation defined.
Well, this is more or less my point.
> To tell the truth, this has always been an unclear point, even in the C
> standard. Given an expression x=y, the expression has a result, which
> is, in the abstract machine, the results of reading the value just written
> to x. Does an implementation have to generate a read of x immediately
> after writing it? (None do, of course, and doing so would be both counter-
> intuitive, and make volatile unusable for at least one of its frequent
> uses.)
>
> My only point was that the abstract machine, at least in C, does do some
> sort of "dereference", which is what makes the expression undefined.
> (The wording in C++ is more complex, and I'm no longer sure about what
> it means. For that matter, I'm not even 100% sure that assigning through
> a null pointer is illegal, although I'm sure that the intend is that it be.)
I believe it does the "dereference" in connection with passing
operands to operators. The operators have the side effects.
So we have:
int nv; // Not-volatile
volatile int v; // Volatile
nv = 0;
// The compiler must logically change the value of nv. But
// it isn't required to actually write 0 into any particular
// RAM address; so long as the as-if rule is followed, the
// compiler may be able to optimize it to nothing.
nv = 0;
// In particular, most "optimizing" compilers will make
// this statement a no-op, since nv already has the correct
// value.
v = 0;
// Not so in this case. If we find the correct RAM address for
// v (which, ironically, is implementation-defined), and we
// are able to observe all activity to that address, then we
// must be able to observe the compiler writing a 0 to that
// address for this instruction.
v = 0;
// And again, the compiler isn't allowed to optimize it away --
// it must store 0 in the variable, even though it may look as
// if the variable already holds that value.
nv = v;
// Here, we must read the value from v and use that as the new
// value for nv. Nothing says we must actually write it to nv's
// prior memory location, but certainly we must read v's value
// from RAM, rather than assuming it's still 0.
v = nv;
// And once again, we can get the value for nv any way we like,
// but we must literally write into v's memory location.
nv;
// A compiler doesn't have to be terribly good at optimizing to
// be able to send this whole statement to the bit bucket. But
// consider what happens before optimization. This is a variable
// name, which is an l-value. There is no operator here, so there
// is no side-effect. Why are l-values statements? It has to be
// because l-values can be converted to r-values; recall that
// r-values are explicitly listed as valid expressions, and thus
// valid statements. Does the process of converting the l-value
// into an r-value require the data to be read?
v;
// Again, no operators, so no side effects. I think that a
// compiler is justified in optimizing this away, even though
// it is declared volatile.
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/09/28 Raw View
In article <360EB808.E6BD2E42@ix.netcom.com>,
Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
> Here is the canonical case:
> char array[3];
> char* array_end() {
> return &array[3];
> }
> Is this legal or isn't it? I say it certainly _ought_ to be legal,
> because the "array[3]" is never actually dereferenced in any physical
> sense. You say it shouldn't (and that one should therefore be required
> to write "return array+3;"), because a debugging compiler might want to
> insert a run-time check that array[3] is dereferencable, even though it
> can plainly see that the what is done with the result is just to take
> its address. That seems to me to be a pretty useless restriction, in
> support of some semantic nit that can better be solved by making the
> rules better reflect the underlying physical reality.
It isn't legal, because array[3] is defined as equivalent to *(array+3),
and the effect of applying unary * to a pointer that is not the address of
an object is undefined. The fact that *(array+3) is used only as an operand
of unary & is irrelevant.
On the other hand, there's nothing wrong with
char* array_end() {
return array+3;
}
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/29 Raw View
Francis Glassborow wrote:
>
> In article <Ezy2IG.6CH@research.att.com>, Andrew Koenig
> <ark@research.att.com> writes
> >Not true.
> >
> >Consider a debugging compiler that checks, every time it forms an address,
> >that the address is a valid one. Under such a compiler, &(*(array+3)) should
> >do the following:
> >
> > Form the address array+3.
> > Verify that the address is valid.
> > Yield that address as its result.
> >
> >The same compiler, given (array+3), should omit the second step.
>
> And then there is the small issue that &, *, + and [] are all operators
> that can be overloaded:)
Not for arrays; only for array elements.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Chris Kuan <look@sig.please>
Date: 1998/09/29 Raw View
Andrew Koenig wrote:
>
> In article <360EBABC.5CB52F74@ix.netcom.com>,
> Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
>
> > Andrew Koenig wrote:
>
> > > > I guess the standard doesn't spell it out literally, but a &
> > > > completely cancels out a *.
> But *z is undefined unless z points to an object, and if *z is undefined,
> so is &*z.
> It provides no benefit at all, but that's the way the rules are anyway.
> I don't like them any more than you do, but disliking them doesn't change them.
But changing them does :-)
What I mean is:
(From the draft C standard)
Committee Draft -- August 3, 1998 WG14/N843
6.5.3.2 Address and indirection operators
Semantics
[#3] The result of the unary & (address-of) operator is a
pointer to the object or function designated by its operand.
If the operand has type ``type'', the result has type
``pointer to type''. If the operand is the result of a
unary * operator, neither that operator nor the & operator
is evaluated, and the result is as if both were omitted,
except that the constraints on the operators still apply and
the result is not an lvalue. Similarly, if the operand is
the result of a [] operator, neither the & operator nor the
unary * that is implied by the [] is evaluated, and the
result is as if the & operator were removed and the []
operator were changed to a + operator.
Could this be adopted for C++2003?
--
Chris Kuan, BHP Information Technology
Concatenate for email: mr gazpacho @ hotmail . com
Phone : +61 2 4275 5555 Fax : +61 2 4275 5547
"A Design Pattern is something that got left out of the language"
- Richard O'Keefe
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/09/29 Raw View
In article <360C69E1.D15FD20D@ix.netcom.com>,
"Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
> Andrew Koenig wrote:
> >
> > In both C and C++, &array[3] means the same as &(*(array+3)). The
> > subexpression *(array+3) is undefined, so &array[3] is undefined.
> > If you want the address of element 3 (i.e. where the fourth element
> > would be if it existed) of the array, you should write (array+3),
> > not &array[3].
Aren't these exactly completely identical, semantics-wise?
> > The C++ standards committee considered relaxing the rules to permit
> > &array[3], but its members could not come up with a way of expressing
> > the relaxed rule that they found convincing.
Where is the rule, the one they left alone?
> This is starting to get silly. A compiler writer would have to stand on
> his head to make &array[3] do anything different from array+3. If they
[snip]
> One of the consequences of this is that it would be valid to add any
> number to any (non-void) pointer, even if the result points way outside
> the object pointed to. You wouldn't be able to dereference the pointer,
> though, unless you subtracted an equivalent amount to bring it back
> within the proper range.
Perhaps, although requiring it might shoot to heck certain formerly
"easy" optimizations. I'm not certain of this, not having written an
optimizing compiler, and never having written assembly code for a
system with (a) special register(s) used for indirection. But it seems
to me that if pointers (or at least temporary values created by pointer
math) are allowed to hold invalid values, then certain CPUs must put an
extra limit on which registers can be used when pointers aren't
dereferenced. Even the x86 can have problems if noise values are put
into the "extra" segment registers (ES, FS, GS, et. al.), depending
on what mode it's running in. The disoptimization you're listing would
disallow the use of those registers except the exact moment that a
pointer was about to be dereferenced.
> And in practice this should produce no
> difficulties, because the hardware shouldn't validate access on a
> pointer unless physically dereferenced.
Even ignoring the optimization issues above, this is still unrealistic.
As an application programmer, wouldn't you assume that
if (array+3 > array)
was always true? But suppose array is 0xFFE4 on a 16-bit
architecture, and that each array element is 10 bytes long. Then
we have
array+0 = 0xFFE4
array+1 = 0xFFF0
array+2 = 0xFFFA (Not a valid element, but one-past-end is okay)
array+3 = 0x10004 = 0x0004 (16-bit architecture, remember?)
and thus array+3 < array.
> I know there are some architectures in which it is tempting to carry
> pointers in registers that access-check their contents as pointers, but
> this isn't practical in C++ anyway, if for no other reason than that the
> standard already insists that a pointer to one-past-the-end of an array
> is legal.
The example given above, in which we guarantee that AT LEAST ONE
ADDRESSABLE BYTE exists beyond the end of the array, would satisfy
the one-past-the-end requirement but would fail to properly compute
N-past-the-end (N>=2).
The standards committee had to draw the line somewhere. The "obvious"
place was at the end of the array; i.e. if the array size is 2,
then array[0] and array[1] are legal, and array[2] is illegal.
But this would have broken too much code of the form
for (ptr=begin; ptr<=end; ++ptr)
I think that the committee went looking for code of the form
for (ptr=begin; ptr<=begin+1000; ++ptr)
if (ptr <= begin) do_something(ptr);
and didn't find any. (This is pretty stupid code even without the
standard language restriction...) So there wasn't a lot of call to
allow 999-past-the-end, or 100-past-the-end, or even 2-past-the-end,
but they clearly did need to allow 1-past-the-end (even though it
must never be dereferenced), in order to not break a lot of code.
Wisely, that's exactly where they drew the line.
> Protected mode x86 systems (e.g., Win16) don't have this
> problem, even though the segment part of a pointer is customarily kept
> in a segment register, because the segment register isn't involved in
> pointer arithmetic anyway.
I think you're wrong, but even if you're right it shouldn't mean
anything to the standards committee. Or are you suggesting that the
standard should be different for x86 systems than for other systems?
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/09/29 Raw View
> In article <360EB808.E6BD2E42@ix.netcom.com>,
> Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
> > char array[3];
> > char* array_end() {
> > return &array[3];
> > }
In article <F00B9E.58A@research.att.com>,
ark@research.att.com (Andrew Koenig) wrote:
> It isn't legal, because array[3] is defined as equivalent to *(array+3),
> and the effect of applying unary * to a pointer that is not the address of
> an object is undefined. The fact that *(array+3) is used only as an operand
> of unary & is irrelevant.
>
> On the other hand, there's nothing wrong with
>
> char* array_end() {
> return array+3;
> }
This seems incredible; if someone with a less authoritative name
than yours were saying it, I wouldn't believe it. Even with your
name attached, it's hard to accept; please accept the slow-witted
response from me and others.
There are a few cases in C++ where a sub-expression is never
evaluated. One of them is in an argument to sizeof:
sizeof(array[3])
should be equivalent to 1, right? Isn't this true even if the
index (3) is one-past-the-end, or even way-past-the-end?
The argument to unary & must be an r-value, and the compiler must
evaluate it far enough to determine the address. But this sub-
expression never retrieves or processes the value in any way.
Have I been writing unsafe code for all these years, by using
& array[ sizeof(array) / sizeof(array[0]) ]
as the address of one-past-the-end? Should the compiler issue a
diagnostic?
I've used five different compilers on four different OS's, which
I suppose demonstrates nothing except that this particular
"extension" is very common and that the related diagnostic is
rarely implemented... is it required?
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/29 Raw View
In article <3610065D.5ED2@sig.please>, Chris Kuan <look@sig.please>
writes
>Could this be adopted for C++2003?
Well I doubt if it could as is because the C++ wording would be made
more complicated by the existence of user-defined operators.
Francis Glassborow Chair of 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
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/09/29 Raw View
In article <6up8ur$j3f$1@nnrp1.dejanews.com>,
AllanW@my-dejanews.com wrote:
> > In article <360EB808.E6BD2E42@ix.netcom.com>,
> > Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
> > > char array[3];
> > > char* array_end() {
> > > return &array[3];
> > > }
> In article <F00B9E.58A@research.att.com>,
> ark@research.att.com (Andrew Koenig) wrote:
> > It isn't legal, because array[3] is defined as equivalent to *(array+3),
> > and the effect of applying unary * to a pointer that is not the address of
> > an object is undefined. The fact that *(array+3) is used only as an operand
> > of unary & is irrelevant.
> >
> > On the other hand, there's nothing wrong with
> >
> > char* array_end() {
> > return array+3;
> > }
>
> This seems incredible; if someone with a less authoritative name
> than yours were saying it, I wouldn't believe it. Even with your
> name attached, it's hard to accept; please accept the slow-witted
> response from me and others.
The name actually attached to the statement is ISO, since Andy is
just presenting what it says in ISO 9899 and ISO 14882. Is that
name authorative enough?
> There are a few cases in C++ where a sub-expression is never
> evaluated. One of them is in an argument to sizeof:
> sizeof(array[3])
> should be equivalent to 1, right? Isn't this true even if the
> index (3) is one-past-the-end, or even way-past-the-end?
Right. In C, I think that as operand to sizeof is the only time an
expression isn't evaluated.
There is nothing in either standard which says that the operand to
an & operator isn't evaluated.
> The argument to unary & must be an r-value, and the compiler must
^^^^^^^ you mean l-value, of course.
> evaluate it far enough to determine the address. But this sub-
> expression never retrieves or processes the value in any way.
There is no such concept as "partial evaluation" in the standard. An
expression is either evaluated, or it isn't. And the operand of &
must be evaluated.
> Have I been writing unsafe code for all these years, by using
> & array[ sizeof(array) / sizeof(array[0]) ]
> as the address of one-past-the-end? Should the compiler issue a
> diagnostic?
This is undefined behavior. The compiler is not required to issue a
diagnostic. In theory, it might format your hard disk. In practice,
of course, it is perfectly portable; a compiler writer would find it
extremely difficult to implement a conforming compiler in which this
didn't work.
> I've used five different compilers on four different OS's, which
> I suppose demonstrates nothing except that this particular
> "extension" is very common and that the related diagnostic is
> rarely implemented... is it required?
See above. It really shouldn't be that hard to add a special case to
the standard, making this legal. Of course, one could easily argue that
C++ has enough special cases already, and that it isn't worth it.
Frankly, I wouldn't worry about it. This is one of those things that
are going to work, and are thus perfectly portable, even if the standard
doesn't sanction it.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/09/29 Raw View
In article <6up373$caq$1@nnrp1.dejanews.com>, <AllanW@my-dejanews.com> wrote:
> In article <360C69E1.D15FD20D@ix.netcom.com>,
> "Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
> > Andrew Koenig wrote:
> > > In both C and C++, &array[3] means the same as &(*(array+3)). The
> > > subexpression *(array+3) is undefined, so &array[3] is undefined.
> > > If you want the address of element 3 (i.e. where the fourth element
> > > would be if it existed) of the array, you should write (array+3),
> > > not &array[3].
> Aren't these exactly completely identical, semantics-wise?
No they are not. *(array+3) is identical to array[3], but
&array[3] is not identical to (array+3), because the former is
undefined if array has <=3 elements.
> > > The C++ standards committee considered relaxing the rules to permit
> > > &array[3], but its members could not come up with a way of expressing
> > > the relaxed rule that they found convincing.
> Where is the rule, the one they left alone?
It comes from defining the meaning of an expression in terms of the meanings
of its subexpressions. In other words, &array[3] is defined in terms of
array[3], and &array[3] is meaningful only if array[3] is meaningful.
> Even ignoring the optimization issues above, this is still unrealistic.
> As an application programmer, wouldn't you assume that
> if (array+3 > array)
> was always true? But suppose array is 0xFFE4 on a 16-bit
> architecture, and that each array element is 10 bytes long. Then
> we have
> array+0 = 0xFFE4
> array+1 = 0xFFF0
> array+2 = 0xFFFA (Not a valid element, but one-past-end is okay)
> array+3 = 0x10004 = 0x0004 (16-bit architecture, remember?)
> and thus array+3 < array.
We are assuming in this discussion that array has 3 elements, not 2.
So array+2 had better be the address of an element.
If array has >=3 elements, then array+3>array is required to be true.
So the compiler is obligated to store the array in a place that computing
array+3 won't cause address overflow.
On the other hand, if array has <=3 elements, then array+4 is undefined.
> The example given above, in which we guarantee that AT LEAST ONE
> ADDRESSABLE BYTE exists beyond the end of the array, would satisfy
> the one-past-the-end requirement but would fail to properly compute
> N-past-the-end (N>=2).
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/29 Raw View
In article <6up373$caq$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
writes
>> > The C++ standards committee considered relaxing the rules to permit
>> > &array[3], but its members could not come up with a way of expressing
>> > the relaxed rule that they found convincing.
>
>Where is the rule, the one they left alone?
Implicit, at least by one interpretation, (I think) in C89 which is why
C90 has now provided explicit support for such as &array[3]. You can be
sure they would not have wasted time drafting text if there was no need
to do so.
Francis Glassborow Chair of 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
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/09/29 Raw View
In article <360EBABC.5CB52F74@ix.netcom.com>,
"Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
>
> Andrew Koenig wrote:
> >
> > > I guess the standard doesn't spell it out literally, but a &
> > > completely cancels out a *.
> >
> > Why do you think so?
>
> Well, because that's what it _does_! Assuming we're talking about
> built-in types, and not fanciful redefinitions of unary * and &,
> conceptually *x means "what pointer x points to", and &y means "a
> pointer to y." Therefore &*z means "a pointer to what pointer z points
> to," which is to say "z".
&*z means take the address of the results of dereferencing z.
Formally, z MUST be dereferenced; in fact, of course, unless z is declared
volatile, dereferencing results in no change in the observable behavior,
and most compilers will optimize the dereference out of the generated
code. (If, of course, z is declared volatile, the dereference had better
take place.)
> You're arguing that *x means "the object pointer x points to", in which
> case "&*z" would mean "z" plus a validity check.
An operator "operates". The unary * operator dereferences the pointer,
regardless of what operations take place on the results of that dereference.
The optimization of suppressing the dereference if z is not volatile
is an easy one. I would imagine that most compilers implement it.
> Why bother?
To start with, what are you asking for, exactly. That the expression
&*x be legal when x points to an object one past the end of an array.
Except, of course, if x points to a volatile, we do have to access it,
and that can't be legal. So the semantics of the abstract machine must
depend on whether an expression is volatile or not. This would be the
only place in the standard where the semantics of the abstract machine
depend on whether something is volatile or not. The whole point of
volatile is that the semantics of the abstract machine become observable
behavior.
> What
> benefit does that interpretation provide? An access check when *z is
> actually read or written is useful. An access check when *z is
> immediately given to & is an irritation, because it means that one must
> write "array+sizeof(array)" instead of "&array[sizeof(array)]". It is
> especially an irritation since it will probably work flawlessly on every
> compiler in the world, and only fail on some theoretical compiler that
> doesn't yet exist.
I don't think that the access check is the question. To make the expression
legal, you need a special case. The question is: do we want (another)
special case?
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/09/29 Raw View
In article <6up373$caq$1@nnrp1.dejanews.com>,
AllanW@my-dejanews.com wrote:
> In article <360C69E1.D15FD20D@ix.netcom.com>,
> "Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
> > Andrew Koenig wrote:
> > >
> > > In both C and C++, &array[3] means the same as &(*(array+3)). The
> > > subexpression *(array+3) is undefined, so &array[3] is undefined.
> > > If you want the address of element 3 (i.e. where the fourth element
> > > would be if it existed) of the array, you should write (array+3),
> > > not &array[3].
>
> Aren't these exactly completely identical, semantics-wise?
No.
There is actually a real problem here; try declaring array volatile. Sho=
uld
(must) the compiler generate an access at the given address?
> > > The C++ standards committee considered relaxing the rules to permit
> > > &array[3], but its members could not come up with a way of expressi=
ng
> > > the relaxed rule that they found convincing.
>
> Where is the rule, the one they left alone?
The definition of the operators. The current definitions state that 1)
array[i] is exactly equivalent to *(array + i), 2) that the unary *
operator dereferences the expression, and 3) dereferencing an expression
which points to one past the end of an array is undefined behavior.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient=E9e objet --
-- Beratung in objektorientierter Datenverarbeitung
-----=3D=3D Posted via Deja News, The Leader in Internet Discussion =3D=3D=
-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/09/29 Raw View
In article <3610065D.5ED2@sig.please>,
look@sig.please wrote:
> (From the draft C standard)
>
> Committee Draft -- August 3, 1998 WG14/N843
>
> 6.5.3.2 Address and indirection operators
>
> Semantics
>
> [#3] The result of the unary & (address-of) operator is a
> pointer to the object or function designated by its operand.
> If the operand has type ``type'', the result has type
> ``pointer to type''. If the operand is the result of a
> unary * operator, neither that operator nor the & operator
> is evaluated, and the result is as if both were omitted,
> except that the constraints on the operators still apply and
> the result is not an lvalue. Similarly, if the operand is
> the result of a [] operator, neither the & operator nor the
> unary * that is implied by the [] is evaluated, and the
> result is as if the & operator were removed and the []
> operator were changed to a + operator.
>
> Could this be adopted for C++2003?
And, for more immediate concerns: Given that the standard is now
"frozen", is there at least some non-normative way to tell vendors
that this would be a good idea now, even though it isn't required?
Fortunately, nothing in the current standard forbids this from
being implemented right away; the burden is on the programmer, who
may want to assume that this rule exists but can't do so safely.
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/09/24 Raw View
Rolf F. Katzenberger wrote:
>
> The CD2 says (under 8.3.4 Arrays [dcl.array], Section 6):
>
> Except where it has been declared for a class (_over.sub_), the
> subscript operator [] is interpreted in such a way that E1[E2] is
> identical to *((E1)+(E2)).
>
> Now, is
>
> &array[-3]
>
> an undefined expression? Does it mean
>
> &( *((array)+(-3)) )
>
> and therefore the result is undefined, or does it mean
>
> ((array)+(-3)) ?
Well:
(1) it's the behaviour who is undefined, not just the
value returned
(2) the first expression has undefined behaviour iff
the second one has undefined behaviour; both
expressions have the _same_ meaning (w/o overloading,
of course)
(3) if array[-3] means *((array)+(-3)), or *(array+- 3),
then &array[-3] means &*(array+- 3)
--
Valentin Bonnard mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/24 Raw View
Valentin Bonnard wrote:
> Rolf F. Katzenberger wrote:
> > The CD2 says (under 8.3.4 Arrays [dcl.array], Section 6):
> > Except where it has been declared for a class (_over.sub_), the
> > subscript operator [] is interpreted in such a way that E1[E2] is
> > identical to *((E1)+(E2)).
> > Now, is
> >
> > &array[-3]
> >
> > an undefined expression? Does it mean
> >
> > &( *((array)+(-3)) )
> >
> > and therefore the result is undefined, or does it mean
> >
> > ((array)+(-3)) ?
> Well:
> (1) it's the behaviour who is undefined, not just the
> value returned
> (2) the first expression has undefined behaviour iff
> the second one has undefined behaviour; both
> expressions have the _same_ meaning (w/o overloading,
> of course)
> (3) if array[-3] means *((array)+(-3)), or *(array+- 3),
> then &array[-3] means &*(array+- 3)
What you say is true, but there is a related case where the difference
between the two expressions is debatable:
int array[3];
int *pi=&array[4];
It's been argued (I don't remember what the conclusion of the argument
was) that the expression &(*((array)+4)) dereferences the pointer, even
though the value stored at that address needn't actually be retrieved.
This is based upon the idea that 'dereference' is a syntactic concept,
not just a semantic one. It's hard to imagine an implementation where
that would actually cause a problem.
There was talk of adding language to the standard explicitly allowing
'*' on a pointer that is one past the end of an object, as long as the
'*' was immediately preceeded by an '&'. I don't remember whether that
was the C9x standard, or the C++ standard, and I don't know if it was
actually done.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/09/25 Raw View
In article <360AC4BF.3F54@wizard.net>, James Kuyper <kuyper@wizard.net> wrote:
> What you say is true, but there is a related case where the difference
> between the two expressions is debatable:
> int array[3];
> int *pi=&array[4];
> It's been argued (I don't remember what the conclusion of the argument
> was) that the expression &(*((array)+4)) dereferences the pointer, even
> though the value stored at that address needn't actually be retrieved.
The discussion gets more interesting if you talk about &array[3], because
&array[4] would be undefined whether the address is dereferenced or not.
In both C and C++, &array[3] means the same as &(*(array+3)). The
subexpression *(array+3) is undefined, so &array[3] is undefined.
If you want the address of element 3 (i.e. where the fourth element
would be if it existed) of the array, you should write (array+3),
not &array[3].
Please note that this discussion does not gainsay the equivalence between
array[n] and *(array+n).
The C++ standards committee considered relaxing the rules to permit
&array[3], but its members could not come up with a way of expressing
the relaxed rule that they found convincing.
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/26 Raw View
Rolf F. Katzenberger wrote:
>
> The CD2 says (under 8.3.4 Arrays [dcl.array], Section 6):
>
> Except where it has been declared for a class (_over.sub_), the
> subscript operator [] is interpreted in such a way that E1[E2] is
> identical to *((E1)+(E2)).
>
> Now, is
>
> &array[-3]
>
> an undefined expression? Does it mean
>
> &( *((array)+(-3)) )
>
> and therefore the result is undefined, or does it mean
>
> ((array)+(-3)) ?
I guess the standard doesn't spell it out literally, but a & completely
cancels out a *. Anyway, it's probably not worth worrying about. Any
compiler will do the same thing internally, and come up with the same
answer: it will subtract three times the (padded) size of the array
element from the address of the start of the array.
--
Ciao,
Paul
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/09/27 Raw View
In article <3608d894.0@news2.ibm.net>,
rfkat@ibm.net (Rolf F. Katzenberger) wrote:
>
> The CD2 says (under 8.3.4 Arrays [dcl.array], Section 6):
>
> Except where it has been declared for a class (_over.sub_), the
> subscript operator [] is interpreted in such a way that E1[E2] is
> identical to *((E1)+(E2)).
>
> Now, is
> &array[-3]
> an undefined expression? Does it mean
> &( *((array)+(-3)) )
> and therefore the result is undefined, or does it mean
> ((array)+(-3)) ?
These, too, are identical. They even look very similar, if you take
out some of the redundant parenthesis:
&( *((array)+(-3)) ) --> &*(array+-3) --> &*(array-3)
((array)+(-3)) ? --> (array+-3) --> (array-3)
They all mean: Start with the address "array" and subtract three
elements. The result need not be undefined, depending on the
meaning of array:
#include <iostream>
int GetAddressMinusThree(int*array) {
return &array[-3]; // or (array-3) or &*(array-3)
}
int main(){
int a[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
std::cout << "4 - 1 = "
<< GetAddressMinusThree(a+6)-a << std::endl;
}
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/27 Raw View
Andrew Koenig wrote:
>
> In both C and C++, &array[3] means the same as &(*(array+3)). The
> subexpression *(array+3) is undefined, so &array[3] is undefined.
> If you want the address of element 3 (i.e. where the fourth element
> would be if it existed) of the array, you should write (array+3),
> not &array[3].
>
> The C++ standards committee considered relaxing the rules to permit
> &array[3], but its members could not come up with a way of expressing
> the relaxed rule that they found convincing.
This is starting to get silly. A compiler writer would have to stand on
his head to make &array[3] do anything different from array+3. If they
wanted to keep the legalisms pristine, all they needed was a rule that
said that unary * isn't considered to be a dereference if it is canceled
out by a subsequent unary & operator, or by initializing a reference
type.
One of the consequences of this is that it would be valid to add any
number to any (non-void) pointer, even if the result points way outside
the object pointed to. You wouldn't be able to dereference the pointer,
though, unless you subtracted an equivalent amount to bring it back
within the proper range. And in practice this should produce no
difficulties, because the hardware shouldn't validate access on a
pointer unless physically dereferenced.
I know there are some architectures in which it is tempting to carry
pointers in registers that access-check their contents as pointers, but
this isn't practical in C++ anyway, if for no other reason than that the
standard already insists that a pointer to one-past-the-end of an array
is legal. Protected mode x86 systems (e.g., Win16) don't have this
problem, even though the segment part of a pointer is customarily kept
in a segment register, because the segment register isn't involved in
pointer arithmetic anyway.
--
Ciao,
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain.COM (Siemel Naran)
Date: 1998/09/27 Raw View
On 26 Sep 1998 18:15:27 GMT, Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
>I guess the standard doesn't spell it out literally, but a & completely
>cancels out a *. Anyway, it's probably not worth worrying about. Any
>compiler will do the same thing internally, and come up with the same
>answer: it will subtract three times the (padded) size of the array
>element from the address of the start of the array.
Operator* and operator& aren't really inverses of each other. An
implementation may do run time array bounds checking. This is good
for debugging.
Of course, vector<> does have an at() member function, which is
essentially a range checked operator[]. But it's annoying to have to
do all this typing: replace "v.at(3)" with "v[3]".
Finally, a user operator* may be radically different. It may return
a reference not to the entire struct, but rather to one of the data
elements in the struct.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/27 Raw View
In article <360C69E1.D15FD20D@ix.netcom.com>, Paul D. DeRocco
<pderocco@ix.netcom.com> writes
>I know there are some architectures in which it is tempting to carry
>pointers in registers that access-check their contents as pointers, but
>this isn't practical in C++ anyway, if for no other reason than that the
>standard already insists that a pointer to one-past-the-end of an array
>is legal.
Exactly, whatever strategy is used a segment fault must not be issued
for exactly one past the end. The need for that specific requirement
was exactly that all other cases produce undefined behaviour. The
requirement is a requirement on the way memory must be allocated in
systems where access checks are carried out early. (if you use such a
system, you better be very careful when you malloc memory for a dynamic
array)
In the case in question (int array[3]; &(array[3]) ) the problem was
finding a wording that precisely allowed this to work in this instance
and made no guarantees about all others. It works for 1 past the end
but you have no right to assume it will work for anything else. To
allow it in general implies that early access-checking must work. Of
course, just because the Standard does not require it to work does not
require it not to work. Implementors are always entitled to go that one
step more and define undefined behaviour.
Francis Glassborow Chair of 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
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/09/27 Raw View
In article <360C69E1.D15FD20D@ix.netcom.com>,
Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
> Andrew Koenig wrote:
> This is starting to get silly. A compiler writer would have to stand on
> his head to make &array[3] do anything different from array+3.
Not true.
Consider a debugging compiler that checks, every time it forms an address,
that the address is a valid one. Under such a compiler, &(*(array+3)) should
do the following:
Form the address array+3.
Verify that the address is valid.
Yield that address as its result.
The same compiler, given (array+3), should omit the second step.
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/09/28 Raw View
rfkat@ibm.net (Rolf F. Katzenberger) writes:
|> The CD2 says (under 8.3.4 Arrays [dcl.array], Section 6):
|>
|> Except where it has been declared for a class (_over.sub_), the
|> subscript operator [] is interpreted in such a way that E1[E2] is
|> identical to *((E1)+(E2)).
|>
|> Now, is
|>
|> &array[-3]
|>
|> an undefined expression?
It depends on the value of array. If array is the name of a C style
array, the expression results in undefined behavior.
|> Does it mean
|>
|> &( *((array)+(-3)) )
|>
|> and therefore the result is undefined, or does it mean
|>
|> ((array)+(-3)) ?
It doesn't matter. If array is the name of a C style array, the
expression (array - 3) results in undefined behavior.
There is some question if the index is one past the end of the C style
array, e.g.:
char array[ 10 ] ;
char* p = &array[ 10 ] ;
In this context, the expression array+10 is definitey legal.
I have a (very) vague memory of there being a demand for interpretation
about this to the C standards committee. I don't know the results, but
I also seem to recall reading somewhere that the C standards committee
has moved to make this legal in C9x, regardless of its previous status.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient e objet --
-- Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/28 Raw View
In article <Ezy2IG.6CH@research.att.com>, Andrew Koenig
<ark@research.att.com> writes
>Not true.
>
>Consider a debugging compiler that checks, every time it forms an address,
>that the address is a valid one. Under such a compiler, &(*(array+3)) should
>do the following:
>
> Form the address array+3.
> Verify that the address is valid.
> Yield that address as its result.
>
>The same compiler, given (array+3), should omit the second step.
And then there is the small issue that &, *, + and [] are all operators
that can be overloaded:)
Francis Glassborow Chair of 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
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/28 Raw View
Andrew Koenig wrote:
>
> > I guess the standard doesn't spell it out literally, but a &
> > completely cancels out a *.
>
> Why do you think so?
Well, because that's what it _does_! Assuming we're talking about
built-in types, and not fanciful redefinitions of unary * and &,
conceptually *x means "what pointer x points to", and &y means "a
pointer to y." Therefore &*z means "a pointer to what pointer z points
to," which is to say "z".
You're arguing that *x means "the object pointer x points to", in which
case "&*z" would mean "z" plus a validity check. Why bother? What
benefit does that interpretation provide? An access check when *z is
actually read or written is useful. An access check when *z is
immediately given to & is an irritation, because it means that one must
write "array+sizeof(array)" instead of "&array[sizeof(array)]". It is
especially an irritation since it will probably work flawlessly on every
compiler in the world, and only fail on some theoretical compiler that
doesn't yet exist.
--
Ciao,
Paul
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/28 Raw View
Andrew Koenig wrote:
>
> Consider a debugging compiler that checks, every time it forms an
> address, that the address is a valid one. Under such a compiler,
> &(*(array+3)) should do the following:
>
> Form the address array+3.
> Verify that the address is valid.
> Yield that address as its result.
>
> The same compiler, given (array+3), should omit the second step.
Here is the canonical case:
char array[3];
char* array_end() {
return &array[3];
}
Is this legal or isn't it? I say it certainly _ought_ to be legal,
because the "array[3]" is never actually dereferenced in any physical
sense. You say it shouldn't (and that one should therefore be required
to write "return array+3;"), because a debugging compiler might want to
insert a run-time check that array[3] is dereferencable, even though it
can plainly see that the what is done with the result is just to take
its address. That seems to me to be a pretty useless restriction, in
support of some semantic nit that can better be solved by making the
rules better reflect the underlying physical reality.
--
Ciao,
Paul
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/28 Raw View
Siemel Naran wrote:
...
> Finally, a user operator* may be radically different. It may return
> a reference not to the entire struct, but rather to one of the data
> elements in the struct.
I've been assuming that 'array' was declared as a T[], for some type T.
In that case, user-defined operators aren't an issue.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1998/09/28 Raw View
In article <360EBABC.5CB52F74@ix.netcom.com>,
Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
> Andrew Koenig wrote:
> > > I guess the standard doesn't spell it out literally, but a &
> > > completely cancels out a *.
> > Why do you think so?
> Well, because that's what it _does_! Assuming we're talking about
> built-in types, and not fanciful redefinitions of unary * and &,
> conceptually *x means "what pointer x points to", and &y means "a
> pointer to y." Therefore &*z means "a pointer to what pointer z points
> to," which is to say "z".
But *z is undefined unless z points to an object, and if *z is undefined,
so is &*z.
> You're arguing that *x means "the object pointer x points to", in which
> case "&*z" would mean "z" plus a validity check. Why bother? What
> benefit does that interpretation provide? An access check when *z is
> actually read or written is useful. An access check when *z is
> immediately given to & is an irritation, because it means that one must
> write "array+sizeof(array)" instead of "&array[sizeof(array)]". It is
> especially an irritation since it will probably work flawlessly on every
> compiler in the world, and only fail on some theoretical compiler that
> doesn't yet exist.
It provides no benefit at all, but that's the way the rules are anyway.
I don't like them any more than you do, but disliking them doesn't change them.
--
Andrew Koenig
ark@research.att.com
http://www.research.att.com/info/ark
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: rfkat@ibm.net (Rolf F. Katzenberger)
Date: 1998/09/23 Raw View
The CD2 says (under 8.3.4 Arrays [dcl.array], Section 6):
Except where it has been declared for a class (_over.sub_), the
subscript operator [] is interpreted in such a way that E1[E2] is
identical to *((E1)+(E2)).
Now, is
&array[-3]
an undefined expression? Does it mean
&( *((array)+(-3)) )
and therefore the result is undefined, or does it mean
((array)+(-3)) ?
Regards,
Rolf
--
______________________________________________________________________
Rolf F. Katzenberger | Software Developer | Trainer 1998-09-21
Home: http://www.geocities.com/SiliconValley/Park/9557
PGP : http://wwwkeys.pgp.net:11371/pks/lookup?op=get&search=0x3B39491F
(Fingerprint F1C0 3116 F6D4 DA33 E61D D2E4 2FB8 D6B6 3B39 491F)
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]