Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #142551 > unrolled thread

Array-as-pointer Syntax

Started by"David T. Ashley" <dashley@gmail.com>
First post2019-03-28 10:04 -0700
Last post2019-03-29 18:08 +0000
Articles 15 — 9 participants

Back to article view | Back to comp.lang.c


Contents

  Array-as-pointer Syntax "David T. Ashley" <dashley@gmail.com> - 2019-03-28 10:04 -0700
    Re: Array-as-pointer Syntax Bart <bc@freeuk.com> - 2019-03-28 17:18 +0000
      Re: Array-as-pointer Syntax David Brown <david.brown@hesbynett.no> - 2019-03-28 21:31 +0100
    Re: Array-as-pointer Syntax Ian Collins <ian-news@hotmail.com> - 2019-03-29 06:23 +1300
      Re: Array-as-pointer Syntax James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-03-28 12:09 -0700
        Re: Array-as-pointer Syntax Ian Collins <ian-news@hotmail.com> - 2019-03-29 08:21 +1300
        Re: Array-as-pointer Syntax Ike Naar <ike@iceland.freeshell.org> - 2019-03-28 22:59 +0000
          Re: Array-as-pointer Syntax James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-03-28 17:44 -0700
      Re: Array-as-pointer Syntax Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-03-28 20:12 +0000
    Re: Array-as-pointer Syntax James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-03-28 11:57 -0700
      Re: Array-as-pointer Syntax Keith Thompson <kst-u@mib.org> - 2019-03-28 13:57 -0700
        Re: Array-as-pointer Syntax James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-03-28 19:50 -0400
    Re: Array-as-pointer Syntax Keith Thompson <kst-u@mib.org> - 2019-03-28 14:04 -0700
    Re: Array-as-pointer Syntax John Bode <jfbode1029@gmail.com> - 2019-03-29 07:24 -0700
      Re: Array-as-pointer Syntax Ike Naar <ike@iceland.freeshell.org> - 2019-03-29 18:08 +0000

#142551 — Array-as-pointer Syntax

From"David T. Ashley" <dashley@gmail.com>
Date2019-03-28 10:04 -0700
SubjectArray-as-pointer Syntax
Message-ID<761347c7-4f03-42f3-a156-5f357c8ae091@googlegroups.com>
Given:

  int x[1000];

what is the difference between:

   memset(x, 0, sizeof(x));

and

   memset(&x, 0, sizeof(x));

I would think there is NO difference, but I might be missing something ...

[toc] | [next] | [standalone]


#142552

FromBart <bc@freeuk.com>
Date2019-03-28 17:18 +0000
Message-ID<Rl7nE.387201$U64.340233@fx20.am4>
In reply to#142551
On 28/03/2019 17:04, David T. Ashley wrote:
> Given:
> 
>    int x[1000];
> 
> what is the difference between:
> 
>     memset(x, 0, sizeof(x));
> 
> and
> 
>     memset(&x, 0, sizeof(x));
> 
> I would think there is NO difference, but I might be missing something ...
> 

'x' has type pointer-to-int (and points to x[0]), '&x' as type 
'pointer-to-array of 1000 int'.

Since both are converted to the void* type that memset takes, there is 
no difference.

[toc] | [prev] | [next] | [standalone]


#142565

FromDavid Brown <david.brown@hesbynett.no>
Date2019-03-28 21:31 +0100
Message-ID<q7jaup$jkr$1@dont-email.me>
In reply to#142552
On 28/03/2019 18:18, Bart wrote:
> On 28/03/2019 17:04, David T. Ashley wrote:
>> Given:
>>
>>    int x[1000];
>>
>> what is the difference between:
>>
>>     memset(x, 0, sizeof(x));
>>
>> and
>>
>>     memset(&x, 0, sizeof(x));
>>
>> I would think there is NO difference, but I might be missing something 
>> ...
>>
> 
> 'x' has type pointer-to-int (and points to x[0]), '&x' as type 
> 'pointer-to-array of 1000 int'.

"x" has type "array of 1000 int", but it is converted to pointer-to-int 
in this context.

> 
> Since both are converted to the void* type that memset takes, there is 
> no difference.

Yes.

[toc] | [prev] | [next] | [standalone]


#142553

FromIan Collins <ian-news@hotmail.com>
Date2019-03-29 06:23 +1300
Message-ID<gg4e83Far11U15@mid.individual.net>
In reply to#142551
On 29/03/2019 06:04, David T. Ashley wrote:
> Given:
> 
>    int x[1000];
> 
> what is the difference between:
> 
>     memset(x, 0, sizeof(x));
> 
> and
> 
>     memset(&x, 0, sizeof(x));
> 
> I would think there is NO difference, but I might be missing something ...

Check for yourself!

#include <stdio.h>

int main()
{
   int x[111];
   printf( "%p %p\n", x, &x);
}

-- 
Ian.

[toc] | [prev] | [next] | [standalone]


#142559

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-03-28 12:09 -0700
Message-ID<ceac71f4-9948-47a9-a96f-26acdb272b61@googlegroups.com>
In reply to#142553
On Thursday, March 28, 2019 at 1:23:26 PM UTC-4, Ian Collins wrote:
> On 29/03/2019 06:04, David T. Ashley wrote:
> > Given:
> > 
> >    int x[1000];
> > 
> > what is the difference between:
> > 
> >     memset(x, 0, sizeof(x));
> > 
> > and
> > 
> >     memset(&x, 0, sizeof(x));
> > 
> > I would think there is NO difference, but I might be missing something ...
> 
> Check for yourself!
> 
> #include <stdio.h>
> 
> int main()
> {
>    int x[111];
>    printf( "%p %p\n", x, &x);

Not quite correct. When you pass a %p format specifier to printf(), "The
corresponding argument "shall be a pointer to a pointer to void."
(7.21.6.2p12).

You're quite likely to get away with this mistake - on many systems all
pointers (or at least, all pointers to objects) have the same
representation, so it doesn't matter if you pass a pointer of the wrong
type. However, for maximum portability you should cast to void*:

    printf("%p %p\n", (void*)x, (void*)&x);

This wouldn't be a problem for most functions. "If the expression that
denotes the called function has a type that does include a prototype,
the arguments are implicitly converted, as if by assignment, to the
types of the corresponding parameters ... " (6.5.2.2p7). However, that
doesn't apply to functions declared without a prototype, nor does it
apply to the variable arguments of variadic functions such as printf().

[toc] | [prev] | [next] | [standalone]


#142560

FromIan Collins <ian-news@hotmail.com>
Date2019-03-29 08:21 +1300
Message-ID<gg4l62Far11U16@mid.individual.net>
In reply to#142559
On 29/03/2019 08:09, James Kuyper wrote:
> On Thursday, March 28, 2019 at 1:23:26 PM UTC-4, Ian Collins wrote:
>> On 29/03/2019 06:04, David T. Ashley wrote:
>>> Given:
>>>
>>>     int x[1000];
>>>
>>> what is the difference between:
>>>
>>>      memset(x, 0, sizeof(x));
>>>
>>> and
>>>
>>>      memset(&x, 0, sizeof(x));
>>>
>>> I would think there is NO difference, but I might be missing something ...
>>
>> Check for yourself!
>>
>> #include <stdio.h>
>>
>> int main()
>> {
>>     int x[111];
>>     printf( "%p %p\n", x, &x);
> 
> Not quite correct. When you pass a %p format specifier to printf(), "The
> corresponding argument "shall be a pointer to a pointer to void."
> (7.21.6.2p12).
> 
> You're quite likely to get away with this mistake - on many systems all
> pointers (or at least, all pointers to objects) have the same
> representation, so it doesn't matter if you pass a pointer of the wrong
> type. However, for maximum portability you should cast to void*:
> 
>      printf("%p %p\n", (void*)x, (void*)&x);

It was a quick test...

-- 
Ian.

[toc] | [prev] | [next] | [standalone]


#142572

FromIke Naar <ike@iceland.freeshell.org>
Date2019-03-28 22:59 +0000
Message-ID<slrn3m0sq9qkf0.hru.ike@iceland.freeshell.org>
In reply to#142559
On 2019-03-28, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
> On Thursday, March 28, 2019 at 1:23:26 PM UTC-4, Ian Collins wrote:
>> On 29/03/2019 06:04, David T. Ashley wrote:
>> > Given:
>> > 
>> >    int x[1000];
>> > 
>> > what is the difference between:
>> > 
>> >     memset(x, 0, sizeof(x));
>> > 
>> > and
>> > 
>> >     memset(&x, 0, sizeof(x));
>> > 
>> > I would think there is NO difference, but I might be missing something ...
>> 
>> Check for yourself!
>> 
>> #include <stdio.h>
>> 
>> int main()
>> {
>>    int x[111];
>>    printf( "%p %p\n", x, &x);
>
> Not quite correct. When you pass a %p format specifier to printf(), "The
> corresponding argument "shall be a pointer to a pointer to void."
> (7.21.6.2p12).

I think the pointer-to-pointer-to-void is  for *scanf.
For *printf it's pointer-to-void.

[toc] | [prev] | [next] | [standalone]


#142575

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-03-28 17:44 -0700
Message-ID<6f7d8cea-8334-4fdd-9c67-61847a0e9f88@googlegroups.com>
In reply to#142572
On Thursday, March 28, 2019 at 6:59:52 PM UTC-4, Ike Naar wrote:
> On 2019-03-28, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
> > On Thursday, March 28, 2019 at 1:23:26 PM UTC-4, Ian Collins wrote:
> >> On 29/03/2019 06:04, David T. Ashley wrote:
> >> > Given:
> >> > 
> >> >    int x[1000];
> >> > 
> >> > what is the difference between:
> >> > 
> >> >     memset(x, 0, sizeof(x));
> >> > 
> >> > and
> >> > 
> >> >     memset(&x, 0, sizeof(x));
> >> > 
> >> > I would think there is NO difference, but I might be missing something ...
> >> 
> >> Check for yourself!
> >> 
> >> #include <stdio.h>
> >> 
> >> int main()
> >> {
> >>    int x[111];
> >>    printf( "%p %p\n", x, &x);
> >
> > Not quite correct. When you pass a %p format specifier to printf(), "The
> > corresponding argument "shall be a pointer to a pointer to void."
> > (7.21.6.2p12).
> 
> I think the pointer-to-pointer-to-void is  for *scanf.
> For *printf it's pointer-to-void.

I cut-and-pasted from the wrong specification, and didn't even look closely at what I was pasting. Sorry. That should be "The argument shall be a pointer to void." (7.21.6.1p8).

[toc] | [prev] | [next] | [standalone]


#142564

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-03-28 20:12 +0000
Message-ID<875zs2g3mq.fsf@bsb.me.uk>
In reply to#142553
Ian Collins <ian-news@hotmail.com> writes:

> On 29/03/2019 06:04, David T. Ashley wrote:
>> Given:
>>
>>    int x[1000];
>>
>> what is the difference between:
>>
>>     memset(x, 0, sizeof(x));
>>
>> and
>>
>>     memset(&x, 0, sizeof(x));
>>
>> I would think there is NO difference, but I might be missing
>> something ...

There is none, provided there is a prototype declaration for memset
visible at the point of call.  Both x and &x will convert to a void *
pointing to the start of the array.

> Check for yourself!
>
> #include <stdio.h>
>
> int main()
> {
>   int x[111];
>   printf( "%p %p\n", x, &x);

Technically, you need (void *)x, and (void *)&x here because, unlike in
the call to memset, pointer arguments in the ... position of a variadic
function are not converted.  Chances are, it won't matter on your system
with your compiler, but the fact that some system does what you want
can't tell you if the code is correct or not.  Tests can expose bugs but
can't prove correctness.

> }

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#142558

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-03-28 11:57 -0700
Message-ID<4be1835e-b0cb-44ad-b088-ad8e82cde4f0@googlegroups.com>
In reply to#142551
On Thursday, March 28, 2019 at 1:04:43 PM UTC-4, David T. Ashley wrote:
> Given:
> 
>   int x[1000];
> 
> what is the difference between:


As an lvalue of array type, 'x' gets implicitly converted into a pointer
to the first element of that array, x[0], in most contexts (6.3.2.1p3),
including the following one:

>    memset(x, 0, sizeof(x));
> 
> and

However, there are four exceptions to that rule, and &x is one of them
(the other three are as the operands of sizeof or _Alignof, or as a
string literal used to initialize an array of character type). This
results in a pointer to the entire array:

>    memset(&x, 0, sizeof(x));
> 
> I would think there is NO difference, but I might be missing something ...

However, both pointers point at the start of the object they pointing
at, and when converted to void* convert into a pointer to the first byte
of that object. Since x[0] and x itself both start at the same byte,
memset() recieves equivalent values for it's first parameter in both
expressions. It therefore behaves in exactly the same way for both
calls.

[toc] | [prev] | [next] | [standalone]


#142566

FromKeith Thompson <kst-u@mib.org>
Date2019-03-28 13:57 -0700
Message-ID<lnwokiaf92.fsf@kst-u.example.com>
In reply to#142558
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
> On Thursday, March 28, 2019 at 1:04:43 PM UTC-4, David T. Ashley wrote:
[...]
> As an lvalue of array type, 'x' gets implicitly converted into a pointer
> to the first element of that array, x[0], in most contexts (6.3.2.1p3),
> including the following one:
>
>>    memset(x, 0, sizeof(x));
>> 
>> and
>
> However, there are four exceptions to that rule, and &x is one of them
> (the other three are as the operands of sizeof or _Alignof, or as a
> string literal used to initialize an array of character type). This
> results in a pointer to the entire array:
>
>>    memset(&x, 0, sizeof(x));

There are three exceptions, not four.  _Alignof (for unclear reasons)
can only be applied to a parenthesized type name, not to an expression.
Including _Alignof in the list of exceptions was an error in the N1570
draft, corrected in the published C11 standard.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#142573

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-03-28 19:50 -0400
Message-ID<q7jmkt$v33$1@dont-email.me>
In reply to#142566
On 3/28/19 16:57, Keith Thompson wrote:
> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>> On Thursday, March 28, 2019 at 1:04:43 PM UTC-4, David T. Ashley wrote:
> [...]
>> As an lvalue of array type, 'x' gets implicitly converted into a pointer
>> to the first element of that array, x[0], in most contexts (6.3.2.1p3),
>> including the following one:
>>
>>>    memset(x, 0, sizeof(x));
>>>
>>> and
>>
>> However, there are four exceptions to that rule, and &x is one of them
>> (the other three are as the operands of sizeof or _Alignof, or as a
>> string literal used to initialize an array of character type). This
>> results in a pointer to the entire array:
>>
>>>    memset(&x, 0, sizeof(x));
> 
> There are three exceptions, not four.  _Alignof (for unclear reasons)
> can only be applied to a parenthesized type name, not to an expression.
> Including _Alignof in the list of exceptions was an error in the N1570
> draft, corrected in the published C11 standard.

I knew there were such errors n1570.pdf, but I forgot that this was one
of them. Sorry.

[toc] | [prev] | [next] | [standalone]


#142568

FromKeith Thompson <kst-u@mib.org>
Date2019-03-28 14:04 -0700
Message-ID<lnsgv6aex6.fsf@kst-u.example.com>
In reply to#142551
"David T. Ashley" <dashley@gmail.com> writes:
> Given:
>
>   int x[1000];
>
> what is the difference between:
>
>    memset(x, 0, sizeof(x));
>
> and
>
>    memset(&x, 0, sizeof(x));
>
> I would think there is NO difference, but I might be missing something ...

As others have explained, the pointer arguments are of different types,
but they point to the same location, yielding the same value after the
implicit conversion to the parameter type void*.

The phrase "Array-as-pointer syntax" is a bit misleading.  Strictly
speaking, there's no such thing.  It's true that in an expression like

    foo[42]

the subexpression foo can be either of pointer type or of array type --
but in fact the index expression *always* requires one operand of
pointer type and one of integer type.  If the prefix happens to be an
array name, it's implicitly converted to a pointer expression.

Similarly, the first argument to memset() must be a pointer expression.
If it's an array name, the argument expression is implicitly converted
to a pointer expression.

If you think this is all counterintuitive and confusing, I agree -- but
it's important to understand it.

See section 6 of the comp.lang.c FAQ http://www.c-faq.com/

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#142587

FromJohn Bode <jfbode1029@gmail.com>
Date2019-03-29 07:24 -0700
Message-ID<c683d9df-f5c5-4ed7-b614-06644b32cd6d@googlegroups.com>
In reply to#142551
On Thursday, March 28, 2019 at 12:04:43 PM UTC-5, David T. Ashley wrote:
> Given:
> 
>   int x[1000];
> 
> what is the difference between:
> 
>    memset(x, 0, sizeof(x));
> 
> and
> 
>    memset(&x, 0, sizeof(x));
> 
> I would think there is NO difference, but I might be missing something ...

x and &x will evaluate to the same address value, although the types of the expressions
will be different (int * vs int (*)[1000]).  So there is effectively no difference between the
two calls.  

Personally, I'd use the first form.  

[toc] | [prev] | [next] | [standalone]


#142598

FromIke Naar <ike@iceland.freeshell.org>
Date2019-03-29 18:08 +0000
Message-ID<slrn3u9oq9snpo.hs7.ike@iceland.freeshell.org>
In reply to#142587
On 2019-03-29, John Bode <jfbode1029@gmail.com> wrote:
> On Thursday, March 28, 2019 at 12:04:43 PM UTC-5, David T. Ashley wrote:
>> Given:
>> 
>>   int x[1000];
>> 
>> what is the difference between:
>> 
>>    memset(x, 0, sizeof(x));
>> 
>> and
>> 
>>    memset(&x, 0, sizeof(x));
>> 
>> I would think there is NO difference, but I might be missing something ...
>
> x and &x will evaluate to the same address value, although the types of the expressions
> will be different (int * vs int (*)[1000]).  So there is effectively no difference between the
> two calls.  
>
> Personally, I'd use the first form.  

Perhaps the second form would be more consistent.

If x had, for instance, a simple type like 'long' or 'double',
or a struct type, one would certainly use the second form 'memset(&x, 0, sizeof x)',
so why not when x has array type?

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web