 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
S.Tobias Guest
|
Posted: Wed Jan 12, 2005 12:00 am Post subject: Re: pointer to an int array |
|
|
Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> wrote:
| Quote: | On Fri, 07 Jan 2005 22:31:16 +0000, S.Tobias wrote:
*(p + 0)
in which the summation cannot be evaluated because `*p' has an incomplete
type (however I fail to explain exactly why, because this expression doesn't
seem to violate any constraints at the "+" operator; could anyone help?).
In both C90 and C99 the + operator requires a pointer operand to have a
pointer to an object type; an incomplete type is not an object type. This
is a constraint.
|
Ah yes, thank you very much! I failed to check and understand the difference
between object and incomplete types (I thought object types were divided
into complete and incomplete; why is a long story).
I hope the rest of my previous analysis is mostly correct.
I think two things yet need an explanation.
1.
# 6.5.3.2 Address and indirection operators
# Constraints
# [...]
# 2 The operand of the unary * operator shall have pointer type.
a) This clearly allows pointers to incomplete types; why aren't they
generally forbidden?
b) Why can't I apply `*' to pointer to incomplete struct type?
struct notdefinedhereyet *p; //ptr to incomplete type
*p; //compiler refuses to generate code here, why?
2.
# 6.5.8 Relational operators
# [...]
# Constraints
# 2 One of the following shall hold:
# -- both operands have real type;
# -- both operands are pointers to qualified or unqualified
# versions of compatible object types; or
# -- both operands are pointers to qualified or unqualified
# versions of compatible incomplete types.
Why is one allowed to compare pointers either when both are pointers
to complete or both are pointers to incomplete compatible types?
Why a pair one being a pointer to complete and the other to incomplete
version of compatible type is excluded?
--
Stan Tobias
mailx `echo [email]siXtY (AT) FamOuS (DOT) BedBuG.pAlS.INVA[/email]LID | sed s/[[:upper:]]//g`
|
|
| Back to top |
|
 |
Lawrence Kirby Guest
|
Posted: Thu Jan 13, 2005 7:07 pm Post subject: Re: pointer to an int array |
|
|
On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:
....
| Quote: | I think two things yet need an explanation.
1.
# 6.5.3.2 Address and indirection operators
# Constraints
# [...]
# 2 The operand of the unary * operator shall have pointer type.
a) This clearly allows pointers to incomplete types; why aren't they
generally forbidden?
|
Some reasons
1. &*p is valid. This might appear for example in macro expansions
2. Consider
extern int (*pa)[];
int *p = *pa;
| Quote: | b) Why can't I apply `*' to pointer to incomplete struct type?
struct notdefinedhereyet *p; //ptr to incomplete type
*p; //compiler refuses to generate code here, why?
|
Don't know, looks OK to me, as long as p points at a suitable object.
| Quote: | 2.
# 6.5.8 Relational operators
# [...]
# Constraints
# 2 One of the following shall hold:
# -- both operands have real type;
# -- both operands are pointers to qualified or unqualified
# versions of compatible object types; or
# -- both operands are pointers to qualified or unqualified
# versions of compatible incomplete types.
Why is one allowed to compare pointers either when both are pointers
to complete or both are pointers to incomplete compatible types?
Why a pair one being a pointer to complete and the other to incomplete
version of compatible type is excluded?
|
Very good question. If nobody comes up with an answer maybe ask on
comp.std.c.
Lawrence
|
|
| Back to top |
|
 |
S.Tobias Guest
|
Posted: Thu Jan 13, 2005 10:21 pm Post subject: Re: pointer to an int array |
|
|
Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> wrote:
| Quote: | On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:
# 2 The operand of the unary * operator shall have pointer type.
a) This clearly allows pointers to incomplete types; why aren't they
generally forbidden?
|
Dereferencing a pointer yields an lvalue. Since incomplete type
doesn't fully describe an object, the result can't be a "good lvalue".
My personal feeling was that it would be more natural that
by default pointers to incomplete types be forbidden, except
in special cases.
| Quote: | 1. &*p is valid. This might appear for example in macro expansions
extern int (*pa)[];
int *p = *pa;
|
Yes, these are those special cases, in which the dereferenced pointer
does not denote an lvalue (1. `*' is canceled by `&'; 2. result is
immediately converted to another type).
| Quote: | b) Why can't I apply `*' to pointer to incomplete struct type?
struct notdefinedhereyet *p; //ptr to incomplete type
*p; //compiler refuses to generate code here, why?
Don't know, looks OK to me, as long as p points at a suitable object.
Why is one allowed to compare pointers either when both are pointers
to complete or both are pointers to incomplete compatible types?
Why a pair one being a pointer to complete and the other to incomplete
version of compatible type is excluded?
Very good question. If nobody comes up with an answer maybe ask on
comp.std.c.
|
Thank you. I'll ask all of these questions again in c.s.c. in a few
days (if nobody...).
--
Stan Tobias
mailx `echo [email]siXtY (AT) FamOuS (DOT) BedBuG.pAlS.INVA[/email]LID | sed s/[[:upper:]]//g`
|
|
| Back to top |
|
 |
Lawrence Kirby Guest
|
Posted: Fri Jan 14, 2005 11:49 am Post subject: Re: pointer to an int array |
|
|
On Thu, 13 Jan 2005 22:21:41 +0000, S.Tobias wrote:
| Quote: | Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> wrote:
On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:
# 2 The operand of the unary * operator shall have pointer type.
a) This clearly allows pointers to incomplete types; why aren't they
generally forbidden?
Dereferencing a pointer yields an lvalue.
|
Dereferencing a pointer can yield an lvalue. However the text of the
standard looks terminally broken in this respect. I should probably check
defects.
Essentially the problem is that the concept of lvalue is used in
constraint specifications (e.g. 6.5.16p2) which means that it is a
property that must be determinable at compile time, i.e. from static
analysis of the source code. C99 6.5.3.2p4 says
"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."
This is a specification for lvalue-ness based on a runtime property i.e.
whether the pointer points at an object or not, which makes it unworkable.
C99 6.3.2.1 says:
"An lvalue is an expression with an object type or an incomplete type
other than void;"
Note specifically that lvalues can have an incomplete type which is good
and correct. This of course has its own problems, apparently saying that
the expression 42 is an lvalue.
| Quote: | Since incomplete type
doesn't fully describe an object, the result can't be a "good lvalue".
|
But it can be an lvalue. For example
extern int a[];
a[0] = 1;
Here a has an incomplete type but because it is an lvalue is is still
converted to a pointer to its first element in an expression.
| Quote: | My personal feeling was that it would be more natural that
by default pointers to incomplete types be forbidden, except
in special cases.
|
I see no reason for this. If you allow void * you have to deal with
pointers to incomplete types one way or another. Using pointers to
incomplete structure types is a valid and important approach for
abstraction and information hiding.
| Quote: | 1. &*p is valid. This might appear for example in macro expansions
extern int (*pa)[];
int *p = *pa;
Yes, these are those special cases, in which the dereferenced pointer
does not denote an lvalue (1. `*' is canceled by `&'; 2. result is
immediately converted to another type).
|
In the 2nd case *pa must be an lvalue for this to work.
....
Lawrence
|
|
| Back to top |
|
 |
Keith Thompson Guest
|
Posted: Fri Jan 14, 2005 9:14 pm Post subject: Re: pointer to an int array |
|
|
Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> writes:
[...]
| Quote: | Dereferencing a pointer can yield an lvalue. However the text of the
standard looks terminally broken in this respect. I should probably check
defects.
|
Yes, the standard's definition of "lvalue" is badly broken.
C90 6.2.2.1 says:
An _lvalue_ is an expression (with an object type or an incomplete
type other than void) that designates an object.
The problem with this definition is that, strictly speaking, you can't
determine at compilation time whether something is an lvalue or not.
Given a declaration
int *ptr;
the expression *ptr designates an object only if current the value of
ptr is non-null. Presumably the intent was that *ptr is an lvalue
regardless of the current value of ptr (and evaluating it invokes
undefined behavior if ptr happens to be null), but the definition
doesn't capture that intent.
C99 6.3.2.1 corrects this problem, but introduces a bigger one:
An _lvalue_ is an expression with an object type or an incomplete
type other than void; if an lvalue does not designate an object
when it is evaluated, the behavior is undefined.
This captures the idea that "*ptr" is an lvalue even if ptr==NULL --
but it also implies that 42 is an lvalue (because it's an expression
with an object type). It no longer says that an lvalue denotes an
object (which is what the concept of "lvalue" is all about), it merely
threatens undefined behavior if it doesn't.
The standard needs to say that an lvalue is an expression that either
denotes an object, or would denote an object if its subexpressions had
the right values. The trick is expressing this in sufficiently
rigorous standardese.
I raised this issue on comp.std.c a few months ago, but the discussion
wasn't productive.
--
Keith Thompson (The_Other_Keith) [email]kst-u (AT) mib (DOT) org[/email] <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
|
|
| Back to top |
|
 |
Al Bowers Guest
|
Posted: Sat Jan 15, 2005 5:13 am Post subject: Re: pointer to an int array |
|
|
Keith Thompson wrote:
| Quote: | Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> writes:
[...]
Dereferencing a pointer can yield an lvalue. However the text of the
standard looks terminally broken in this respect. I should probably check
defects.
Yes, the standard's definition of "lvalue" is badly broken.
C90 6.2.2.1 says:
An _lvalue_ is an expression (with an object type or an incomplete
type other than void) that designates an object.
The problem with this definition is that, strictly speaking, you can't
determine at compilation time whether something is an lvalue or not.
Given a declaration
int *ptr;
the expression *ptr designates an object only if current the value of
ptr is non-null.
|
A value of non-null doesn't assure *ptr designate an object.
Given:
int *ptr = malloc(0);
ptr need not have the value of NULL.
So, is *ptr an object where ptr a value of NULL or some other
implementation defined value? Either way, *ptr cannot be used to
access an object.
--
Al Bowers
Tampa, Fl USA
mailto: [email]xabowers (AT) myrapidsys (DOT) com[/email] (remove the x to send email)
http://www.geocities.com/abowers822/
|
|
| Back to top |
|
 |
Keith Thompson Guest
|
Posted: Sat Jan 15, 2005 7:45 am Post subject: Re: pointer to an int array |
|
|
Al Bowers <xabowers (AT) rapidsys (DOT) com> writes:
| Quote: | Keith Thompson wrote:
Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> writes:
[...]
Dereferencing a pointer can yield an lvalue. However the text of the
standard looks terminally broken in this respect. I should probably check
defects.
Yes, the standard's definition of "lvalue" is badly broken.
C90 6.2.2.1 says:
An _lvalue_ is an expression (with an object type or an
incomplete
type other than void) that designates an object.
The problem with this definition is that, strictly speaking, you
can't
determine at compilation time whether something is an lvalue or not.
Given a declaration
int *ptr;
the expression *ptr designates an object only if current the value of
ptr is non-null.
A value of non-null doesn't assure *ptr designate an object.
Given:
int *ptr = malloc(0);
ptr need not have the value of NULL.
So, is *ptr an object where ptr a value of NULL or some other
implementation defined value? Either way, *ptr cannot be used to
access an object.
|
Right, which is why I wrote "only if" above, not "if and only if"
(though I could have been more specific).
The point is that "lvalue" is intended to be a compile-time concept,
so *ptr should be considered an lvalue regardless of the current value
of ptr.
--
Keith Thompson (The_Other_Keith) [email]kst-u (AT) mib (DOT) org[/email] <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
|
|
| Back to top |
|
 |
S.Tobias Guest
|
Posted: Sun Jan 16, 2005 1:28 am Post subject: Re: pointer to an int array |
|
|
Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> wrote:
| Quote: | On Thu, 13 Jan 2005 22:21:41 +0000, S.Tobias wrote:
Lawrence Kirby <lknews (AT) netactive (DOT) co.uk> wrote:
On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:
# 2 The operand of the unary * operator shall have pointer type.
a) This clearly allows pointers to incomplete types; why aren't they
generally forbidden?
Dereferencing a pointer yields an lvalue.
Dereferencing a pointer can yield an lvalue.
[snip] |
And when it doesn't?
| Quote: | Essentially the problem is that the concept of lvalue is used in
constraint specifications (e.g. 6.5.16p2) which means that it is a
property that must be determinable at compile time, i.e. from static
analysis of the source code. C99 6.5.3.2p4 says
"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."
This is a specification for lvalue-ness based on a runtime property i.e.
whether the pointer points at an object or not, which makes it unworkable.
|
I understand your point. However, on second thought, this is not a
definition. What is says is that `*p' 1. designates the object `p'
points to (and not some other), and 2. is an lvalue (the expression can
potentially exist in any position where an lvalue is expected).
If `p' does not point to any valid object, `*p' raises UB (because
the Standard fails to define it); past this point there is no need to
consider whether `*p' is an lvalue or not, the behaviour is undefined
anyway. (The case of &*p has been covered in earlier section.)
| Quote: | C99 6.3.2.1 says:
"An lvalue is an expression with an object type or an incomplete type
other than void;"
|
This is the definition. Lvalue is compile-time concept.
| Quote: | Note specifically that lvalues can have an incomplete type which is good
and correct. This of course has its own problems, apparently saying that
the expression 42 is an lvalue.
Since incomplete type
doesn't fully describe an object, the result can't be a "good lvalue".
|
I wrote this because my idea of lvalue was not the same as in the
Standard. Thanks for pointing this out to me (I also thank Keith
Thompson for his post). I start to feel that the concept of lvalue
is not only semantical (object designator), but also it is a "label"
that takes part in grammatical analysis of expressions; maybe this is
the reason why certain rules seem a little confusing.
I think I need to stop right here and think things over again, I really
can't add anything productive at this point. Discussing with you has
been very enlightening for me, thanks a lot!
struct mystruct *p;
*p; //gcc refused to compile
The last sentence in 6.3.2.1p2 (incredible how I selectively read that
text) says, referring to lvalues not being an operand to unary & and
other operators:
# If the lvalue has an incomplete type and does not have array type,
# the behavior is undefined.
which covers my previous question. However, I wouldn't like a compiler
that would issue only a warning.
--
Stan Tobias
mailx `echo [email]siXtY (AT) FamOuS (DOT) BedBuG.pAlS.INVA[/email]LID | sed s/[[:upper:]]//g`
|
|
| Back to top |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|