Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > pointer to an int array

Reply
Thread Tools

pointer to an int array

 
 
Neo
Guest
Posts: n/a
 
      01-04-2005

"Stan Milam" <(E-Mail Removed)> wrote in message
news:5EpCd.10716$(E-Mail Removed) om...
> Jack Klein wrote:
>
>> On Mon, 3 Jan 2005 12:44:42 +0530, "Neo" <(E-Mail Removed)>
>> 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


 
Reply With Quote
 
 
 
 
Jens.Toerring@physik.fu-berlin.de
Guest
Posts: n/a
 
      01-04-2005
Stan Milam <(E-Mail Removed)> 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 ___ http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de
\__________________________ http://www.toerring.de
 
Reply With Quote
 
 
 
 
Lawrence Kirby
Guest
Posts: n/a
 
      01-04-2005
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
 
Reply With Quote
 
S.Tobias
Guest
Posts: n/a
 
      01-07-2005
Mark McIntyre <(E-Mail Removed)> wrote:
> On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
> <(E-Mail Removed)> 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 http://www.velocityreviews.com/forums/(E-Mail Removed)LID | sed s/[[:upper:]]//g`
 
Reply With Quote
 
Lawrence Kirby
Guest
Posts: n/a
 
      01-11-2005
On Fri, 07 Jan 2005 22:31:16 +0000, S.Tobias wrote:

> Mark McIntyre <(E-Mail Removed)> wrote:
>> On Mon, 3 Jan 2005 14:01:44 +0530, in comp.lang.c , "Neo"
>> <(E-Mail Removed)> 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

 
Reply With Quote
 
S.Tobias
Guest
Posts: n/a
 
      01-12-2005
Lawrence Kirby <(E-Mail Removed)> 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 (E-Mail Removed)LID | sed s/[[:upper:]]//g`
 
Reply With Quote
 
Lawrence Kirby
Guest
Posts: n/a
 
      01-13-2005
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

 
Reply With Quote
 
S.Tobias
Guest
Posts: n/a
 
      01-13-2005
Lawrence Kirby <(E-Mail Removed)> 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 (E-Mail Removed)LID | sed s/[[:upper:]]//g`
 
Reply With Quote
 
Lawrence Kirby
Guest
Posts: n/a
 
      01-14-2005
On Thu, 13 Jan 2005 22:21:41 +0000, S.Tobias wrote:

> Lawrence Kirby <(E-Mail Removed)> 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
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-14-2005
Lawrence Kirby <(E-Mail Removed)> 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) (E-Mail Removed) <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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
what is it for an array ? int f(int VAR) { int tab[VAR]; .. } Alain Spineux C Programming 6 05-17-2011 01:03 AM
Difference between int i, j; and int i; int j; arun C Programming 8 07-31-2006 05:11 AM
int main(int argc, char *argv[] ) vs int main(int argc, char **argv ) Hal Styli C Programming 14 01-20-2004 10:00 PM
How to combine 2 int Array into ONE int Array ? S300 Java 4 08-19-2003 07:04 PM
dirty stuff: f(int,int) cast to f(struct{int,int}) Schnoffos C Programming 2 06-27-2003 03:13 AM



Advertisments