470,594 Members | 1,429 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,594 developers. It's quick & easy.

pointer to an int array

Neo
Hi Folks,
#include<stdio.h>
int main()
{
int (*p)[10];
int arr[10];
int i;

p = arr; /* <-- compiler warning */
for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
*((*p) + i) = i;

printf("%d\n", p[0][i]);
}

return 0;
}

In the above program compiler is giving following warning

$gcc pointer2array.c
pointer2array.c: In function `main':
pointer2array.c:8: warning: assignment from incompatible pointer type

Why the warning?

O'kay and what is the use of int (*p)[10] type of declaration ?
Does the compiler perform any check on the array bounds?
lets say if i declare int arr[12]...
-Neo
Nov 14 '05 #1
22 1954
On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <ti***************@yahoo.com>
wrote in comp.lang.c:
Hi Folks,
#include<stdio.h>
int main()
{
int (*p)[10];
int arr[10];
int i;

p = arr; /* <-- compiler warning */
The name of an array in an expression, other than when it is the
operand of the 'sizeof' or '&' operators, is converted to a pointer to
its first element. So in the statement above, you are assigning the
address of an int (arr[0]) to a pointer to an array. But arr[0] is an
int, not an array of ints.

Replace with:

p = &arr;
for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
*((*p) + i) = i;

printf("%d\n", p[0][i]);
}

return 0;
}

In the above program compiler is giving following warning

$gcc pointer2array.c
pointer2array.c: In function `main':
pointer2array.c:8: warning: assignment from incompatible pointer type

Why the warning?

O'kay and what is the use of int (*p)[10] type of declaration ?
Does the compiler perform any check on the array bounds?
lets say if i declare int arr[12]...


--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #2
Neo

"Jack Klein" <ja*******@spamcop.net> wrote in message
news:db********************************@4ax.com...
On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <ti***************@yahoo.com>
wrote in comp.lang.c:
Hi Folks,
#include<stdio.h>
int main()
{
int (*p)[10];
int arr[10];
int i;

p = arr; /* <-- compiler warning */


The name of an array in an expression, other than when it is the
operand of the 'sizeof' or '&' operators, is converted to a pointer to
its first element. So in the statement above, you are assigning the
address of an int (arr[0]) to a pointer to an array. But arr[0] is an
int, not an array of ints.

Replace with:

p = &arr;


O'kay, dats fine.
if I change the declaration above as :

int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with
unspecified bounds
int arr[10];
p = &arr;
for(i=0; i <= 12; i++){
*((*p) + i) = i;
printf("%d\n", p[0][i]);
}

compiler error!
what's the use of array index in the above declaration?
as i can go upto 12 or more...

-Neo
for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
*((*p) + i) = i;

printf("%d\n", p[0][i]);
}

return 0;
}

In the above program compiler is giving following warning

$gcc pointer2array.c
pointer2array.c: In function `main':
pointer2array.c:8: warning: assignment from incompatible pointer type

Why the warning?

O'kay and what is the use of int (*p)[10] type of declaration ?
Does the compiler perform any check on the array bounds?
lets say if i declare int arr[12]...


--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html

Nov 14 '05 #3
On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
<ti***************@yahoo.com> wrote:
if I change the declaration above as :

int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with unspecified bounds

compiler error!
yes, its an error
what's the use of array index in the above declaration?
none - its an illegal construct
as i can go upto 12 or more...


only by invoking undefined behaviour....

Don't do that.
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #4
You can index up to whatever value you want. p[1000] is fine. The
result is going to be undefined. In most cases you would get a seg
fault but that may not be the case. You have to do the bounds checking
yourself.

Nov 14 '05 #5
"gooch" <go******@comcast.net> wrote:

[ Using Google-Broken-Beta is not an excuse not to show any context.
Learn to use it to quote properly or get a real newsreader. Context
reinstated. ]
"Neo" <ti***************@yahoo.com> wrote:
if I change the declaration above as :

int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with
unspecified bounds
int arr[10];
p = &arr;
for(i=0; i <= 12; i++){
*((*p) + i) = i;
printf("%d\n", p[0][i]);
}

compiler error!
what's the use of array index in the above declaration?
as i can go upto 12 or more...
You can index up to whatever value you want. p[1000] is fine. The
result is going to be undefined.
I don't see how you can write those sentences together. The result of
p[10] and over are indeed going to be undefined, which is exactly why
such indices are _not_ fine.
In most cases you would get a seg fault but that may not be the case.


If you're lucky, you'll get a segfault. If you're unlucky, you won't see
the segfault, but your customer will. If you're _really_ unlucky,
neither of you will get a segfault, but your program will slowly
scribble over all your customer's data, and he'll sue you. Don't run
over the end of your arrays, not even when you think "it'll be safe,
because you'll get a segfault anyway".

Richard
Nov 14 '05 #6
"I don't see how you can write those sentences together. ....."

I am not saying it is a good thing or that you should do it, only that
it is not a legal operation.

"If you're lucky, you'll get a segfault. ....."

Again I am not suggesting he assume a segfault will occur, only that he
needs to do the bounds checking himself.

Nov 14 '05 #7
On 3 Jan 2005 10:19:39 -0800, in comp.lang.c , "gooch"
<go******@comcast.net> wrote:

(contextless stuff)

please read the VERY FIRST THING that richard said in his last post to you.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 14 '05 #8
"gooch" <go******@comcast.net> writes:
You can index up to whatever value you want. p[1000] is fine. The
result is going to be undefined. In most cases you would get a seg
fault but that may not be the case. You have to do the bounds checking
yourself.


(I presume p is an array with fewer than 1001 elements.)

p[1000] is not "fine" in any sense of the word. It is a serious error
that the implementation is not required to diagnose. This can
sometimes have the same visible results as something that's perfectly
legal, but the distinction is critical.

Incidentally, it's not true that "in most cases you would get a seg
fault". Attempting to access an array beyond its bounds is very
likely to refer to some other variable in your program, with
unpredictable results.

Your overall point, that you have to do your own bounds checking
because the implementation won't do it for you, is quite correct; I'm
just (over)reacting to your use of the word "fine".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 14 '05 #9
Jack Klein wrote:
On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <ti***************@yahoo.com>
wrote in comp.lang.c:

Hi Folks,
#include<stdio.h>
int main()
{
int (*p)[10];
int arr[10];
int i;

p = arr; /* <-- compiler warning */

The name of an array in an expression, other than when it is the
operand of the 'sizeof' or '&' operators, is converted to a pointer to
its first element. So in the statement above, you are assigning the
address of an int (arr[0]) to a pointer to an array. But arr[0] is an
int, not an array of ints.

Replace with:

p = &arr;

for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
*((*p) + i) = i;

printf("%d\n", p[0][i]);
}

return 0;
}

In the above program compiler is giving following warning

$gcc pointer2array.c
pointer2array.c: In function `main':
pointer2array.c:8: warning: assignment from incompatible pointer type

Why the warning?

O'kay and what is the use of int (*p)[10] type of declaration ?
Does the compiler perform any check on the array bounds?
lets say if i declare int arr[12]...


Okay, both of you are mistaken. int (*p)[10] is declaring an array of
10 pointers to function that return integers. Not quite the same thing
as either of you are talking about.

--
Regards,
Stan Milam.
-----------------------------------------------------------------------------
Vita Brevis. Carpe Guitarum! - Jamie Kinscherff
-----------------------------------------------------------------------------
Nov 14 '05 #10
Neo

"Stan Milam" <st*****@swbell.net> wrote in message
news:5E******************@newssvr11.news.prodigy.c om...
Jack Klein wrote:
On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <ti***************@yahoo.com>
wrote in comp.lang.c:

Hi Folks,
#include<stdio.h>
int main()
{
int (*p)[10];
int arr[10];
int i;

p = arr; /* <-- compiler warning */

The name of an array in an expression, other than when it is the
operand of the 'sizeof' or '&' operators, is converted to a pointer to
its first element. So in the statement above, you are assigning the
address of an int (arr[0]) to a pointer to an array. But arr[0] is an
int, not an array of ints.

Replace with:

p = &arr;

for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
*((*p) + i) = i;

printf("%d\n", p[0][i]);
}

return 0;
}

In the above program compiler is giving following warning

$gcc pointer2array.c
pointer2array.c: In function `main':
pointer2array.c:8: warning: assignment from incompatible pointer type

Why the warning?

O'kay and what is the use of int (*p)[10] type of declaration ?
Does the compiler perform any check on the array bounds?
lets say if i declare int arr[12]...


Okay, both of you are mistaken. int (*p)[10] is declaring an array of 10
pointers to function that return integers. Not quite the same thing as
either of you are talking about.

--
Regards,
Stan Milam.
-----------------------------------------------------------------------------
Vita Brevis. Carpe Guitarum! - Jamie Kinscherff
-----------------------------------------------------------------------------


pointers to function???
hmm.... its a pointer to arrary of 10 INTs!
-Neo
Nov 14 '05 #11
Stan Milam <st*****@swbell.net> wrote:
Okay, both of you are mistaken. int (*p)[10] is declaring an array of
10 pointers to function that return integers. Not quite the same thing
as either of you are talking about.


Sorry, but no.

int ( *p )[ 10 ];

is a pointer to an array of 10 ints. The parentheses here are needed to
distinguish it from

int *p[ 10 ];

which would be an array of 10 pointers to int. An array of 10 pointers
to functions that return int would be

int ( *p[ 10 ] )( );

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #12
On Mon, 03 Jan 2005 12:44:42 +0530, Neo wrote:
Hi Folks,
#include<stdio.h>
int main()
{
int (*p)[10];
int arr[10];
int i;

p = arr; /* <-- compiler warning */
for(i=0; i <= 12; i++){ /* i <=12 delibrately written code */
*((*p) + i) = i;

printf("%d\n", p[0][i]);
}

return 0;
}

In the above program compiler is giving following warning

$gcc pointer2array.c
pointer2array.c: In function `main':
pointer2array.c:8: warning: assignment from incompatible pointer type

Why the warning?
Becuase you are trying to assign a value of type int * to a variable of
type int (*)[10]. C doesn't support implicit conversion between these
types. You could write

p = &arr;

but there isn't anything obvious to be gained over defining p as int *.
O'kay and what is the use of int (*p)[10] type of declaration ?
You could use this in something like the following

int arr2[5][10];
int (*p2)[10] = arr2;

Then accessing p2[x][y] will access the element arr2[x][y]
Does
the compiler perform any check on the array bounds? lets say if i
declare int arr[12]...


C doesn't require any sort of bounds checking from the compiler, and most
don't attempt to.

Lawrence
Nov 14 '05 #13
Mark McIntyre <ma**********@spamcop.net> wrote:
On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
<ti***************@yahoo.com> wrote:
if I change the declaration above as :

int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with unspecified bounds

compiler error! yes, its an error
IMHO I think you're wrong here. `p' is simply a pointer to incomplete type
("array of int of unknown size").

The OP probably hadn't noticed that the error was at different line:
printf("%d\n", p[0][i]); //error
Exactly, the offending expression is p[0], because, it gets translated
to:
*(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?).

The above expression can be corrected with:
(*p)[i];
This is interesting, because we seem to apply indirection operator to
pointer to incomplete type (again, this is not a constraint violation,
however it doesn't work with pointers to incomplete struct type; could
someone help explain this please?); but here lvalue `*p', which is
of "array of int" type, is converted to "pointer to int" and points
to its first element, essentially same location as the array itself;
this rule seems to take precedence.

what's the use of array index in the above declaration?
Type `int[]' is compatible with `int[10]' and `int[20]',
so `p' could be assigned an address of objects defined as:
int a[15];
int b[80];
double d[10]; //except this object
p = &a;
p = &b;
p = &d; //error
However, since `p' is a pointer to incomplete type, no arithmetic or
comparisons can be made with it.
I think one can describe `p' as a generic pointer to "arrays of int".
I don't know if it could be more useful than that.
as i can go upto 12 or more...

only by invoking undefined behaviour....


Yes.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #14
On Fri, 07 Jan 2005 22:31:16 +0000, S.Tobias wrote:
Mark McIntyre <ma**********@spamcop.net> wrote:
On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
<ti***************@yahoo.com> wrote:

>if I change the declaration above as :
>
> int (*p)[]; <-- pointer2array.c:12: error: invalid use of array with unspecified bounds
>
>compiler error!

yes, its an error


IMHO I think you're wrong here. `p' is simply a pointer to incomplete type
("array of int of unknown size").

The OP probably hadn't noticed that the error was at different line:
printf("%d\n", p[0][i]); //error
Exactly, the offending expression is p[0], because, it gets translated
to:
*(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.

Lawrence

Nov 14 '05 #15
Lawrence Kirby <lk****@netactive.co.uk> wrote:
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 si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #16
On Wed, 12 Jan 2005 00:00:17 +0000, S.Tobias wrote:

....
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;

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

Nov 14 '05 #17
Lawrence Kirby <lk****@netactive.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. 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.
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).

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 si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #18
On Thu, 13 Jan 2005 22:21:41 +0000, S.Tobias wrote:
Lawrence Kirby <lk****@netactive.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.
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.
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.
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
Nov 14 '05 #19
Lawrence Kirby <lk****@netactive.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. 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) ks***@mib.org <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.
Nov 14 '05 #20


Keith Thompson wrote:
Lawrence Kirby <lk****@netactive.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: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #21
Al Bowers <xa******@rapidsys.com> writes:
Keith Thompson wrote:
Lawrence Kirby <lk****@netactive.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) ks***@mib.org <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.
Nov 14 '05 #22
Lawrence Kirby <lk****@netactive.co.uk> wrote:
On Thu, 13 Jan 2005 22:21:41 +0000, S.Tobias wrote:
Lawrence Kirby <lk****@netactive.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?
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.)
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.
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 si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #23

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Bruno van Dooren | last post: by
204 posts views Thread by Alexei A. Frounze | last post: by
28 posts views Thread by Wonder | last post: by
8 posts views Thread by Martin Jřrgensen | last post: by
1 post views Thread by Tomás | last post: by
42 posts views Thread by xdevel | last post: by
26 posts views Thread by aruna.mysore | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.