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


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

Pointers, constant values

Started byAlla _ <modelling.data@gmail.com>
First post2015-10-16 00:49 -0700
Last post2015-10-17 13:59 -0700
Articles 20 on this page of 77 — 14 participants

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


Contents

  Pointers, constant values Alla _ <modelling.data@gmail.com> - 2015-10-16 00:49 -0700
    Re: Pointers, constant values Philip Lantz <prl@canterey.us> - 2015-10-16 01:49 -0700
    Re: Pointers, constant values James Kuyper <jameskuyper@verizon.net> - 2015-10-16 09:41 -0400
      Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 08:55 -0700
    Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 08:25 -0700
      Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 09:11 -0700
        Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 12:06 -0700
          Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 12:55 -0700
      Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-16 17:49 +0100
        Re: Pointers, constant values Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2015-10-16 13:23 -0400
          Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-16 19:34 +0100
            Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 12:05 -0700
          Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 12:18 -0700
        Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 12:13 -0700
          Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-16 20:33 +0100
            Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 13:01 -0700
              Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-16 21:09 +0100
                Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 13:41 -0700
            Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-16 21:07 +0100
              Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-16 21:20 +0100
                Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-16 22:02 +0100
                  Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-16 22:21 +0100
                    Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 14:39 -0700
                      Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 15:26 -0700
                        Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 15:44 -0700
                          Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 16:58 -0700
                            Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 17:28 -0700
                    Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-16 22:50 +0100
                      Re: Pointers, constant values supercat@casperkitty.com - 2015-10-16 15:14 -0700
                      Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-17 01:23 +0100
                        Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-17 19:39 +0100
                          Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-17 22:42 +0100
                            Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-18 00:31 +0100
                              Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-18 02:11 +0100
                                Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-18 11:59 +0100
                                  Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-18 12:12 +0100
                                    Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-18 12:28 +0100
                                    Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-18 23:16 +0100
                                      Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-18 23:34 +0100
                                        Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-19 01:45 +0100
                                          Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-19 11:51 +0100
                                            Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-19 12:55 +0100
                                              Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-19 13:51 +0100
                                                Re: Pointers, constant values Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-19 06:02 -0700
                                                  Re: Pointers, constant values supercat@casperkitty.com - 2015-10-19 07:02 -0700
                                                    Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-19 15:39 +0100
                                                      Re: Pointers, constant values supercat@casperkitty.com - 2015-10-19 08:54 -0700
                                                        Re: Pointers, constant values Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-19 09:14 -0700
                                                          Re: Pointers, constant values supercat@casperkitty.com - 2015-10-19 10:21 -0700
                                                            Re: Pointers, constant values Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-19 12:57 -0700
                                                Re: Pointers, constant values glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-10-19 21:20 +0000
                                                  Re: Pointers, constant values supercat@casperkitty.com - 2015-10-20 20:50 -0700
                                                    Re: Pointers, constant values glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-10-21 04:58 +0000
                                          Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-19 08:40 -0700
                                            Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-19 20:17 +0100
                            Re: Pointers, constant values supercat@casperkitty.com - 2015-10-17 16:44 -0700
                              Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-18 11:52 +0100
                                Re: Pointers, constant values Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-18 05:15 -0700
                                  Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-18 21:54 +0100
                                    Re: Pointers, constant values Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-18 16:09 -0700
                                Re: Pointers, constant values supercat@casperkitty.com - 2015-10-18 07:55 -0700
                                  Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-18 21:47 +0100
                                    Re: Pointers, constant values supercat@casperkitty.com - 2015-10-18 15:37 -0700
                                      Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-19 00:10 +0100
                                        Re: Pointers, constant values supercat@casperkitty.com - 2015-10-18 19:04 -0700
          Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-16 21:13 +0100
        Re: Pointers, constant values Ian Collins <ian-news@hotmail.com> - 2015-10-17 11:27 +1300
          Re: Pointers, constant values Bartc <bc@freeuk.com> - 2015-10-17 00:56 +0100
    Re: Pointers, constant values Les Cargill <lcargill99@comcast.com> - 2015-10-16 12:37 -0500
      Re: Pointers, constant values James Kuyper <jameskuyper@verizon.net> - 2015-10-16 14:22 -0400
    Re: Pointers, constant values Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-10-16 18:57 +0000
      Re: Pointers, constant values Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-16 20:40 +0100
        Re: Pointers, constant values Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-10-16 20:46 +0000
          Re: Pointers, constant values Keith Thompson <kst-u@mib.org> - 2015-10-16 14:24 -0700
            Re: Pointers, constant values Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-10-19 12:43 +0000
    Re: Pointers, constant values Siri Cruz <chine.bleu@yahoo.com> - 2015-10-16 13:20 -0700
      Re: Pointers, constant values supercat@casperkitty.com - 2015-10-17 13:59 -0700

Page 1 of 4  [1] 2 3 4  Next page →


#73016 — Pointers, constant values

FromAlla _ <modelling.data@gmail.com>
Date2015-10-16 00:49 -0700
SubjectPointers, constant values
Message-ID<5b2ab074-7644-4798-9b90-a3ae47e1f2b8@googlegroups.com>
Hello!

I have not yet solved issues discussed in my
previous posts; I will get back to them tomorrow.
Meanwhile, following recommendations, I am reading
the chapter on pointers. 

I would be grateful for your help in understanding 
few questions on using constants.

char c = 'x';
char * const char_pointer = &c; means that the pointer
variable char_pointer will always be pointing to 
char variable named c, therefore char_pointer = &d
will be an error.

Does this mean (I am trying to make sure I understand
this correctly) that char c can equal anything, and its
value can be changed within a program a few times, but 
char_pointer will always point to c and its changing
values?

On the other hand,

const char *char_pointer = &c; means that the value of c 
will be constant, will not change no matter what; and 
the pointer will not be able to assign a different value to
char c; if char c initially equals 'x', the pointer 
will not be able to assign 'b' to it, is this correct? 

Please, also take a look at the program below:

// Function to sum the elements of an integer array

#include <stdio.h>

int array_sum (int array[], const int n);

int main (void)
{
    int values[5] = {3, 7, -9, 5, 2};
    
    printf ("The sum is %i\n", array_sum (values, 5));
    
    return 0;
}

int array_sum (int array[], const int n)
{
    int sum = 0;
    int *pointer;
    int * const array_end = array + n;
    
   /** constant integer pointer array_end is defined and set 
        pointing immediately after the last element of array. **/
    
    for (pointer = array; pointer < array_end; pointer++)
        sum += *pointer;
    /** Each time through the loop, the element of array pointed to by 
        pointer is added into sum. **/
    /** The value of pointer is then incremented by the for loop to set 
        it pointing to the next element in array. **/
    return sum;
}

Does int * const array_end = array + n; mean that the pointer
array_end has a constant value of array[0] + n, or that it will not 
be able to change the value of (array + n)?

Thank you!

[toc] | [next] | [standalone]


#73017

FromPhilip Lantz <prl@canterey.us>
Date2015-10-16 01:49 -0700
Message-ID<MPG.308a59dcaaa7d78177@news.eternal-september.org>
In reply to#73016
Alla _ wrote:
> char c = 'x';
> char * const char_pointer = &c; means that the pointer
> variable char_pointer will always be pointing to 
> char variable named c, therefore char_pointer = &d
> will be an error.

Yes.

> Does this mean (I am trying to make sure I understand
> this correctly) that char c can equal anything, and its
> value can be changed within a program a few times, but 
> char_pointer will always point to c and its changing
> values?

Yes.

> const char *char_pointer = &c; means that the value of c 
> will be constant, will not change no matter what; and 
> the pointer will not be able to assign a different value to
> char c; if char c initially equals 'x', the pointer 
> will not be able to assign 'b' to it, is this correct? 

You cannot assign a new value 'b' to c using the pointer, but you can 
assign a different value to c directly, with c = 'b'; and then if you 
read the value using the pointer, you will see the new value 'b'.

> // Function to sum the elements of an integer array
> 
> #include <stdio.h>
> 
> int array_sum (int array[], const int n);
> 
> int main (void)
> {
>     int values[5] = {3, 7, -9, 5, 2};
>     
>     printf ("The sum is %i\n", array_sum (values, 5));
>     
>     return 0;
> }
> 
> int array_sum (int array[], const int n)
> {
>     int sum = 0;
>     int *pointer;
>     int * const array_end = array + n;
>     
>    /** constant integer pointer array_end is defined and set 
>         pointing immediately after the last element of array. **/
>     
>     for (pointer = array; pointer < array_end; pointer++)
>         sum += *pointer;
>     /** Each time through the loop, the element of array pointed to by 
>         pointer is added into sum. **/
>     /** The value of pointer is then incremented by the for loop to set 
>         it pointing to the next element in array. **/
>     return sum;
> }
> 
> Does int * const array_end = array + n; mean that the pointer
> array_end has a constant value of array[0] + n, or that it will not 
> be able to change the value of (array + n)?

It means that array_end has a constant value of &array[0] + n. However, 
you cannot read or assign through this pointer, because it is past the 
end of the array. (But that's not because of the 'const'.) The const 
means that the pointer itself cannot be changed.

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


#73028

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-10-16 09:41 -0400
Message-ID<mvqun3$d2n$1@dont-email.me>
In reply to#73016
On 10/16/2015 03:49 AM, Alla _ wrote:
...
> const char *char_pointer = &c; means that the value of c 
> will be constant, will not change no matter what; and 
> the pointer will not be able to assign a different value to
> char c; if char c initially equals 'x', the pointer 
> will not be able to assign 'b' to it, is this correct? 

Not quite. The value of c can be changed, it just can't be changed by
using that pointer. Any attempt to do so should result in a diagnostic
message. Note: a diagnostic message is NOT required if you write
    *(char*)char_pointer = 'a';

Which is one of the key reasons why you should avoid casts unless
absolutely necessary. That code will try to set whatever 'char_pointer'
is pointed at to a value of 'a'. If it's pointed at 'c', the attempt
will succeed. However, if the object it points at is, itself,
const-qualified or a string literal, the behavior is undefined:

const char const_qualified_object = 'A';
char_pointer = &const_qualified_object;
*(char*)char_pointer = 'a';	// Undefined behavior
char_pointer = "String Literal";
*(char*)char_pointer = 's';	// Undefined behavior
-- 
James Kuyper

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


#73040

Fromsupercat@casperkitty.com
Date2015-10-16 08:55 -0700
Message-ID<d2942723-46e7-4dc0-87ab-49b2b947b800@googlegroups.com>
In reply to#73028
On Friday, October 16, 2015 at 8:42:11 AM UTC-5, James Kuyper wrote:
> Not quite. The value of c can be changed, it just can't be changed by
> using that pointer. Any attempt to do so should result in a diagnostic
> message. Note: a diagnostic message is NOT required if you write
>     *(char*)char_pointer = 'a';

In other words, it can't be changed by using that pointer *unless* it is
cast or converted to a non-const pointer.

Some languages have the concept of a read-only pointer which does not allow
"const" to be cast away; such a thing allows a compiler to make assumptions
that would not otherwise be possible.  For example, if "fnord" accepted such
a pointer type, then given:

    int x = 3;
    const *xp = &x;
    fnord(xp);
    x++;
    foo();
    x++;
    bar();

a compiler which couldn't "see into" the aforementioned functions could
replace the code with:

    int x = 3;
    const *xp = &x;
    fnord(xp);
    x=4;
    foo();
    x=5;
    bar();

It wouldn't be able to know whether "fnord" might have stored the address
of x somewhere that "foo" and "bar" could see it, and would thus have to
perform the later writes to x for their benefit, but it would know that
the pointer couldn't have been stored in any fashion that would allow
other code to write to it, and would thus avoid any need to allow for the
possibility of x being changed anywhere else.

Because it is sometimes necessary to have a function accept a pointer that
may or may not be writable and make it available to something that may or
may not write to it, however, it would be unworkable to have a language in
which the only "read-only" pointer types were "strongly read-only", and
since C only has one kind of "read-only" pointer type, it's only weakly
read-only.

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


#73033

FromKeith Thompson <kst-u@mib.org>
Date2015-10-16 08:25 -0700
Message-ID<ln4mhq7s4z.fsf@kst-u.example.com>
In reply to#73016
Alla _ <modelling.data@gmail.com> writes:
[...]
> int array_sum (int array[], const int n);

One piece of advice:

The parameter declaration
    int array[]
really means
    int *array

There is no such thing as an array parameter in C, but it uses
array-like syntax to define pointer variables.

My advice is *not* to take advantage of that special-case rule.  It's a
pointer, so define it as a pointer:

    int array_sum (int *array, const int n);

Not everyone will agree with this; some will argue that using the []
notation is a reminder that it points to an element of an array, not
just a single int object.  Which is a valid point -- but in my opinion
the reminder that it's really a pointer is more valuable.

I'd also pick a name other than "array", because it isn't one.

BTW, C99 added a new use for the "static" keyword:

    void func(int arr[static 10])

which requires the use of array notation.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#73041

Fromsupercat@casperkitty.com
Date2015-10-16 09:11 -0700
Message-ID<ae147956-8353-4b46-b8ae-39512670c8d7@googlegroups.com>
In reply to#73033
On Friday, October 16, 2015 at 10:25:16 AM UTC-5, Keith Thompson wrote:
> Not everyone will agree with this; some will argue that using the []
> notation is a reminder that it points to an element of an array, not
> just a single int object.  Which is a valid point -- but in my opinion
> the reminder that it's really a pointer is more valuable.

How about, following along with the idea of "[static n]", how about adopting
the convention of using "TYPE *name" in cases where the parameter might
sometimes legitimately be null, and "TYPE name[]" in cases where the the
parameter could never legitimately be null.  Using that convention...

     void process_things(THING *things, int n);

would suggest that process_things(NULL, 0); would do nothing, while

     void process_things(THING things[], int n);

would suggest that it must never be.  The C language itself makes no
distinction between the two cases above, but I would suggest that since
the language allows both forms, it might be useful to have them mean
different things by convention.  A linter could then be configured to
squawk any time a function with the latter prototype is invoked with
something that might be null, or when a function with the former
prototype would fail if passed null and doesn't use a directive to
account for that, e.g.

    void process_things(THING *things, int n)
    {
      if (n <= 0) return;
      __CHECKED_ASSUME(things != null);
      for (int i=0; i<n; i++)
        process_thing(things[i]);
    }

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


#73057

FromKeith Thompson <kst-u@mib.org>
Date2015-10-16 12:06 -0700
Message-ID<lnd1we63bl.fsf@kst-u.example.com>
In reply to#73041
supercat@casperkitty.com writes:
> On Friday, October 16, 2015 at 10:25:16 AM UTC-5, Keith Thompson wrote:
>> Not everyone will agree with this; some will argue that using the []
>> notation is a reminder that it points to an element of an array, not
>> just a single int object.  Which is a valid point -- but in my opinion
>> the reminder that it's really a pointer is more valuable.
>
> How about, following along with the idea of "[static n]", how about adopting
> the convention of using "TYPE *name" in cases where the parameter might
> sometimes legitimately be null, and "TYPE name[]" in cases where the the
> parameter could never legitimately be null.  Using that convention...
>
>      void process_things(THING *things, int n);
>
> would suggest that process_things(NULL, 0); would do nothing, while
>
>      void process_things(THING things[], int n);
>
> would suggest that it must never be.
[...]

C already has a notation for asserting that a pointer parameter must be
non-null:

    void process_things(THING things[static 1], int n);

That's "asserting" in the sense that violating the assertion causes undefined
behavior.  Of course you can also add
    assert(things != NULL);
if you like, or treat it as a run-time error, or whatever.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#73063

Fromsupercat@casperkitty.com
Date2015-10-16 12:55 -0700
Message-ID<df46bc88-61d9-4e9f-9bf2-6f62e2d75720@googlegroups.com>
In reply to#73057
On Friday, October 16, 2015 at 2:06:35 PM UTC-5, Keith Thompson wrote:
> C already has a notation for asserting that a pointer parameter must be
> non-null:
> 
>     void process_things(THING things[static 1], int n);
> 
> That's "asserting" in the sense that violating the assertion causes undefined
> behavior.

Consider the following:

    void process_things(THING it[], int n)
    {
      THING *past_end = it+n;
      while(it < past_end)
        process_thing(it++);
    }

I believe that's Undefined Behavior if "it" is null (IIRC, C++ defines
the result of adding zero to a null pointer as being a null pointer,
but C does not), but it's fully defined behavior if "it" is a past-one
pointer and n is zero.  Is there any way to write the prototype that
could tell a linter that?

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


#73043

FromBartc <bc@freeuk.com>
Date2015-10-16 17:49 +0100
Message-ID<mvr9nb$ra4$1@dont-email.me>
In reply to#73033
On 16/10/2015 16:25, Keith Thompson wrote:
> Alla _ <modelling.data@gmail.com> writes:
> [...]
>> int array_sum (int array[], const int n);
>
> One piece of advice:
>
> The parameter declaration
>      int array[]
> really means
>      int *array
>
> There is no such thing as an array parameter in C, but it uses
> array-like syntax to define pointer variables.
>
> My advice is *not* to take advantage of that special-case rule.  It's a
> pointer, so define it as a pointer:
>
>      int array_sum (int *array, const int n);

> Not everyone will agree with this; some will argue that using the []
> notation is a reminder that it points to an element of an array, not
> just a single int object.

But 'int *array' *is* a pointer to a single element. C allows you to 
pass a pointer to an actual array, if not the array itself:

  int array_sum(int (*array)[], int n);

However this also now requires proper array dereferencing and indexing, 
not just applying an offset to an arbitrary pointer which can be to 
anything:

  (*array)[i]

-- 
Bartc

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


#73047

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2015-10-16 13:23 -0400
Message-ID<KoaUx.29137$os5.11289@fx14.iad>
In reply to#73043
On Friday October 16 2015 12:49, in comp.lang.c, "Bartc" <bc@freeuk.com>
wrote:

> On 16/10/2015 16:25, Keith Thompson wrote:
>> Alla _ <modelling.data@gmail.com> writes:
>> [...]
>>> int array_sum (int array[], const int n);
>>
>> One piece of advice:
>>
>> The parameter declaration
>>      int array[]
>> really means
>>      int *array
>>
>> There is no such thing as an array parameter in C, but it uses
>> array-like syntax to define pointer variables.
>>
>> My advice is *not* to take advantage of that special-case rule.  It's a
>> pointer, so define it as a pointer:
>>
>>      int array_sum (int *array, const int n);
> 
>> Not everyone will agree with this; some will argue that using the []
>> notation is a reminder that it points to an element of an array, not
>> just a single int object.
> 
> But 'int *array' *is* a pointer to a single element. C allows you to
> pass a pointer to an actual array, if not the array itself:
> 
>   int array_sum(int (*array)[], int n);

That's one way of looking at it. OTOH, you can also interpret <<array>> above
as a pointer-to a pointer-to an int. In other words, you haven't really
passed "a pointer to an actual array", but instead have passed a pointer to a
pointer (that, hopefully, points to at least one element of an array). Now,
you have two problems instead of one. 

Keith is correct: as a function parameter declaration (sans C99's
alternative):
    int array[]
really does mean
    int *array

This leads to two conditions that the function should (I would say "must")
test before <<array>> can actually be considered an array (and accessed as
such):
1) does <<array>> point to something or is it NULL?
2) how many entities can be legitimately addressed through <<array>>?

If I could, I would add a third condition, between #1 and #2 ("Does <<array>>
contain a valid pointer?") if such a condition were testable. This would
ensure that, if not NULL, the pointer <<array>> pointed to an existing object
of correct type.

> However this also now requires proper array dereferencing and indexing,
> not just applying an offset to an arbitrary pointer which can be to
> anything:
> 
>   (*array)[i]

I fail to see how this suggestion simplifies or solves the problem. It /does/
add another pointer, which will have to be validated, and complicates the
logic that both the caller and the called functions must implement. It does
not provide any more safety, nor does it address
the "*(pointer+displacement)" vs "pointer[displacement]" debate.

I do concur with Keith for the most part, but I differ (slightly) in his
characterization of the benefit of the "*(pointer+displacement)" argument.
Where he says:
> some will argue that using the [] notation is a reminder that it points to
> an element of an array, not just a single int object. 
I would rephrase that as
  some will argue that using the [] notation is a reminder that it IS INTENDED 
  to point to an element of an array, not just a single int object.
(caps to show the difference in phrasing)
Hopefully, when using the [] notation, both the caller and the called
function /agree/ that the parameter is intended to point to an array.
 
-- 
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

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


#73053

FromBartc <bc@freeuk.com>
Date2015-10-16 19:34 +0100
Message-ID<mvrfri$j7e$1@dont-email.me>
In reply to#73047
On 16/10/2015 18:23, Lew Pitcher wrote:
> On Friday October 16 2015 12:49, in comp.lang.c, "Bartc" <bc@freeuk.com>
> wrote:
>> On 16/10/2015 16:25, Keith Thompson wrote:

>>> Not everyone will agree with this; some will argue that using the []
>>> notation is a reminder that it points to an element of an array, not
>>> just a single int object.
>>
>> But 'int *array' *is* a pointer to a single element. C allows you to
>> pass a pointer to an actual array, if not the array itself:
>>
>>    int array_sum(int (*array)[], int n);
>
> That's one way of looking at it. OTOH, you can also interpret <<array>> above
> as a pointer-to a pointer-to an int. In other words, you haven't really
> passed "a pointer to an actual array", but instead have passed a pointer to a
> pointer (that, hopefully, points to at least one element of an array). Now,
> you have two problems instead of one.

No, I've passed a pointer to an array. (Cdecl tells me the function 
takes a 'pointer to array of int'.)

Perhaps you're confused by the fact that, in order to do access an 
element of the array inside the function, then the array name, 'array', 
'decomposes' to a pointer to the first element. In other words, int**. 
But this is just a C thing.

As an example, if I have 'static int A[100]'; in the caller, where A is 
at address 0x4674, and call array_sum(A,1), then I'm passing 0x4674. I'm 
not passing the address of an another location that contains 0x4764.

While inside array_sum(), it's only doing one dereference to access 
A[0]. (That extra dereference is another bit of a confusion that C likes 
to throw your way.)

>> However this also now requires proper array dereferencing and indexing,
>> not just applying an offset to an arbitrary pointer which can be to
>> anything:
>>
>>    (*array)[i]
>
> I fail to see how this suggestion simplifies or solves the problem. It /does/
> add another pointer,

No, it doesn't. But it does mean that you have to explicitly dereference 
this pointer-to-array in a way that you don't need with pointer-to-int. 
And the syntax for that is ugly. That's why nobody uses it.

> which will have to be validated,

That's the idea: that you don't unintentionally pass something that is 
not a pointer to an array. Take these three versions of array_sum:

  int array_sum1(int X[],    int n) {return X[0];}
  int array_sum2(int *X,     int n) {return X[0];}
  int array_sum3(int (*X)[], int n) {return (*X)[0];}

The third of these passes an actual pointer-to-array. In the caller:

  int B[100];

  array_sum1(B,100);
  array_sum2(B,100);
  array_sum3(&B,100);

Notice that the third requires you to explicitly pass the 
pointer-to-array, and won't accept just 'B', which is a pointer-to-int.

It's clearer here:

  int C;

  array_sum1(&C,100);
  array_sum2(&C,100);
  array_sum3(&C,100);

The compiler doesn't complain about the first two; that's the problem. 
It does rightly complain about the third form.

> I would rephrase that as
>    some will argue that using the [] notation is a reminder that it IS INTENDED
>    to point to an element of an array, not just a single int object.
> (caps to show the difference in phrasing)
> Hopefully, when using the [] notation, both the caller and the called
> function /agree/ that the parameter is intended to point to an array.

This is just another weird thing about C. Because arrays can't be passed 
to functions by value, then instead of a reporting an error when 'int 
A[]' is seen in a parameter list, the meaning is changed to 'int* A'. In 
fact I think all types involving [] in parameter lists are one pointer 
level out of step with the same type spec anywhere else.

-- 
Bartc

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


#73056

Fromsupercat@casperkitty.com
Date2015-10-16 12:05 -0700
Message-ID<7ee9ea07-324a-42ad-9cc2-c6f8259ca7a2@googlegroups.com>
In reply to#73053
On Friday, October 16, 2015 at 1:34:34 PM UTC-5, Bart wrote:
> This is just another weird thing about C. Because arrays can't be passed 
> to functions by value, then instead of a reporting an error when 'int 
> A[]' is seen in a parameter list, the meaning is changed to 'int* A'. In 
> fact I think all types involving [] in parameter lists are one pointer 
> level out of step with the same type spec anywhere else.

In BCPL, the predecessor to C, there were no arrays, but there was a syntax
which was much like "int *foo = calloc(sizeof (int), N)" except that the
block would be statically allocated at compile time and could never be
freed.  Aside from the fact that string literals are read-only, the closest
C equivalent to the closest BCPL equivalent to char foo[5]; would be
char *foo = "\0\0\0\0"; [the closing literal brings the total up to five
zero bytes].  K&R wanted to allow code using BCPL types to be changed to
using real array types with minimal impact.  Having arrays decay into
pointers was a means of achieving that.  IMHO, the misstep occurred when
C++ defined its syntax for prototypes (which was then incorporated into
C).  There would have been an opportunity to specify that using array
syntax with or without a dimension would be interpreted differently from
pointer syntax, but that opportunity was not taken.

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


#73059

FromKeith Thompson <kst-u@mib.org>
Date2015-10-16 12:18 -0700
Message-ID<ln4mhq62rz.fsf@kst-u.example.com>
In reply to#73047
Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
> On Friday October 16 2015 12:49, in comp.lang.c, "Bartc" <bc@freeuk.com>
> wrote:
[...]
>> But 'int *array' *is* a pointer to a single element. C allows you to
>> pass a pointer to an actual array, if not the array itself:
>> 
>>   int array_sum(int (*array)[], int n);
>
> That's one way of looking at it. OTOH, you can also interpret <<array>> above
> as a pointer-to a pointer-to an int. In other words, you haven't really
> passed "a pointer to an actual array", but instead have passed a pointer to a
> pointer (that, hopefully, points to at least one element of an array). Now,
> you have two problems instead of one. 

No, `array` is not a pointer to a pointer; it's actually a pointer to an
array.  The problem is that the array type is incomplete, so there's not
much you can do with it.

[...]

> I do concur with Keith for the most part, but I differ (slightly) in his
> characterization of the benefit of the "*(pointer+displacement)" argument.
> Where he says:
>> some will argue that using the [] notation is a reminder that it points to
>> an element of an array, not just a single int object. 
> I would rephrase that as
>   some will argue that using the [] notation is a reminder that it IS INTENDED 
>   to point to an element of an array, not just a single int object.
> (caps to show the difference in phrasing)
> Hopefully, when using the [] notation, both the caller and the called
> function /agree/ that the parameter is intended to point to an array.

Good point.  Using [] notation for a parameter doesn't *enforce*
anything on the caller.

The bottom line, I think, is that array manipulation in C is generally
done via pointers to individual array elements, with other elements
accessed by doing pointer arithmetic.  Array indexing is just a
syntactic wrapper around pointer arithmetic (a[i] means *(a+i)).

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#73058

FromKeith Thompson <kst-u@mib.org>
Date2015-10-16 12:13 -0700
Message-ID<ln8u726308.fsf@kst-u.example.com>
In reply to#73043
Bartc <bc@freeuk.com> writes:
> On 16/10/2015 16:25, Keith Thompson wrote:
>> Alla _ <modelling.data@gmail.com> writes:
>> [...]
>>> int array_sum (int array[], const int n);
>>
>> One piece of advice:
>>
>> The parameter declaration
>>      int array[]
>> really means
>>      int *array
>>
>> There is no such thing as an array parameter in C, but it uses
>> array-like syntax to define pointer variables.
>>
>> My advice is *not* to take advantage of that special-case rule.  It's a
>> pointer, so define it as a pointer:
>>
>>      int array_sum (int *array, const int n);
>
>> Not everyone will agree with this; some will argue that using the []
>> notation is a reminder that it points to an element of an array, not
>> just a single int object.
>
> But 'int *array' *is* a pointer to a single element.

Yes.  Isn't that pretty much what I said?  It's a pointer to an int
object; using array notation suggests that that object is the initial
element of an array.  (Then again, for at least some purposes *any*
single object can be treated as an element of a 1-element array.)


>                                                      C allows you to
> pass a pointer to an actual array, if not the array itself:
>
>  int array_sum(int (*array)[], int n);

Yes, but there's not much you can do with it, since you haven't
specified the length of the array it points to.  (I'm a little surprised
that that declaration is legal.)

> However this also now requires proper array dereferencing and
> indexing, not just applying an offset to an arbitrary pointer which
> can be to anything:
>
>  (*array)[i]

That won't compile unless you have something between the [] in the
declaration.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#73060

FromBartc <bc@freeuk.com>
Date2015-10-16 20:33 +0100
Message-ID<mvrjar$2ji$1@dont-email.me>
In reply to#73058
On 16/10/2015 20:13, Keith Thompson wrote:
> Bartc <bc@freeuk.com> writes:

>>   int array_sum(int (*array)[], int n);
>
> Yes, but there's not much you can do with it, since you haven't
> specified the length of the array it points to.  (I'm a little surprised
> that that declaration is legal.)

It's a pointer to an unbounded array. You can do anything you like with 
it except anything involving its length. But int* doesn't have a length 
either.

Actually, requiring a bound to be specified would severely restrict it 
as you it would then only work for arrays of that length. Although you 
might of course want that behaviour: if you implement a 3D point as 
float (*)[3], you don't want anything passing other other kind of array.


>> However this also now requires proper array dereferencing and
>> indexing, not just applying an offset to an arbitrary pointer which
>> can be to anything:
>>
>>   (*array)[i]
>
> That won't compile unless you have something between the [] in the
> declaration.

It works because I've tried it. (I wouldn't use this style of parameter 
passing if writing actual C, it's too fiddly, but my generated code 
always uses proper pointer-to-arrays.)

-- 
Bartc

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


#73064

FromKeith Thompson <kst-u@mib.org>
Date2015-10-16 13:01 -0700
Message-ID<lnpp0e4m7s.fsf@kst-u.example.com>
In reply to#73060
Bartc <bc@freeuk.com> writes:
> On 16/10/2015 20:13, Keith Thompson wrote:
>> Bartc <bc@freeuk.com> writes:
>
>>>   int array_sum(int (*array)[], int n);
>>
>> Yes, but there's not much you can do with it, since you haven't
>> specified the length of the array it points to.  (I'm a little surprised
>> that that declaration is legal.)
>
> It's a pointer to an unbounded array. You can do anything you like with 
> it except anything involving its length. But int* doesn't have a length 
> either.

No, but int* specifies the size of the object it points to.  Given int
(*array)[], you don't even know the size of the element type.

> Actually, requiring a bound to be specified would severely restrict it 
> as you it would then only work for arrays of that length. Although you 
> might of course want that behaviour: if you implement a 3D point as 
> float (*)[3], you don't want anything passing other other kind of array.
>
>
>>> However this also now requires proper array dereferencing and
>>> indexing, not just applying an offset to an arbitrary pointer which
>>> can be to anything:
>>>
>>>   (*array)[i]
>>
>> That won't compile unless you have something between the [] in the
>> declaration.
>
> It works because I've tried it. (I wouldn't use this style of parameter 
> passing if writing actual C, it's too fiddly, but my generated code 
> always uses proper pointer-to-arrays.)

$ cat c.c
int array_sum(int (*array)[], int n) {
    array[0];
}
$ gcc -c c.c
c.c: In function 'array_sum':
c.c:2: error: invalid use of array with unspecified bounds
$ 

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#73066

FromBartc <bc@freeuk.com>
Date2015-10-16 21:09 +0100
Message-ID<mvrle8$akl$1@dont-email.me>
In reply to#73064
On 16/10/2015 21:01, Keith Thompson wrote:
> Bartc <bc@freeuk.com> writes:

>> It's a pointer to an unbounded array. You can do anything you like with
>> it except anything involving its length. But int* doesn't have a length
>> either.
>
> No, but int* specifies the size of the object it points to.  Given int
> (*array)[], you don't even know the size of the element type.

It's pointer to an array of int. The element size is the size of int.

> $ cat c.c
> int array_sum(int (*array)[], int n) {
>      array[0];
> }
> $ gcc -c c.c
> c.c: In function 'array_sum':
> c.c:2: error: invalid use of array with unspecified bounds
> $

You forget to put in 'return'. And you haven't dereferenced the array 
properly. Try writing it as:

  return (*array)[0];

I'm not suggested everyone does this, because just passing int pointers 
for arrays is simpler and is very widespread and well understood.

But if the syntax wasn't so clunky, this ought to be the recommended way 
of passing pointers to arrays.

-- 
Bartc

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


#73071

FromKeith Thompson <kst-u@mib.org>
Date2015-10-16 13:41 -0700
Message-ID<lnfv1a4kcj.fsf@kst-u.example.com>
In reply to#73066
Bartc <bc@freeuk.com> writes:
> On 16/10/2015 21:01, Keith Thompson wrote:
>> Bartc <bc@freeuk.com> writes:
>>> It's a pointer to an unbounded array. You can do anything you like with
>>> it except anything involving its length. But int* doesn't have a length
>>> either.
>>
>> No, but int* specifies the size of the object it points to.  Given int
>> (*array)[], you don't even know the size of the element type.
>
> It's pointer to an array of int. The element size is the size of int.
>
>> $ cat c.c
>> int array_sum(int (*array)[], int n) {
>>      array[0];
>> }
>> $ gcc -c c.c
>> c.c: In function 'array_sum':
>> c.c:2: error: invalid use of array with unspecified bounds
>> $
>
> You forget to put in 'return'.

I didn't forget it.  My intent was to show that it doesn't compile,
regardless of how it's used.  However ...

>                                And you haven't dereferenced the array
> properly. Try writing it as:
>
>  return (*array)[0];
>
> I'm not suggested everyone does this, because just passing int
> pointers for arrays is simpler and is very widespread and well
> understood.
>
> But if the syntax wasn't so clunky, this ought to be the recommended
> way of passing pointers to arrays.

You're right, you had (*array)[i] in your previous article and I missed
it.  Never mind.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#73065

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-10-16 21:07 +0100
Message-ID<87io66r30y.fsf@bsb.me.uk>
In reply to#73060
Bartc <bc@freeuk.com> writes:

> On 16/10/2015 20:13, Keith Thompson wrote:
>> Bartc <bc@freeuk.com> writes:
>
>>>   int array_sum(int (*array)[], int n);
>>
>> Yes, but there's not much you can do with it, since you haven't
>> specified the length of the array it points to.  (I'm a little surprised
>> that that declaration is legal.)
>
> It's a pointer to an unbounded array.

It's a pointer to an incomplete array type and, as such, is compatible
with a pointer to an int array of any length.  Talking about an
unbounded array in C sounds very odd to me (but I did know what you
mean).

In C99 there's no reason not to go the whole hog and write

  int array_sum(int n, int (*data)[n]) { ... }

Now you *can* ask about sizeof *data, and even the usual ARRAY_SIZE
macro trick will work[1].  Of course the answer will be n, so there's
not much point, but then there was not much point in passing a pointer
to an array in the first place!

[1] I.e.
    #define ARRAY_SIZE(a) (sizeof (a) / sizeof (a)[0])
-- 
Ben.

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


#73068

FromBartc <bc@freeuk.com>
Date2015-10-16 21:20 +0100
Message-ID<mvrm33$d10$1@dont-email.me>
In reply to#73065
On 16/10/2015 21:07, Ben Bacarisse wrote:
> Bartc <bc@freeuk.com> writes:
>
>> On 16/10/2015 20:13, Keith Thompson wrote:
>>> Bartc <bc@freeuk.com> writes:
>>
>>>>    int array_sum(int (*array)[], int n);
>>>
>>> Yes, but there's not much you can do with it, since you haven't
>>> specified the length of the array it points to.  (I'm a little surprised
>>> that that declaration is legal.)
>>
>> It's a pointer to an unbounded array.
>
> It's a pointer to an incomplete array type and, as such, is compatible
> with a pointer to an int array of any length.  Talking about an
> unbounded array in C sounds very odd to me (but I did know what you
> mean).

It's the error you get if you compile with g++; it talks about unknown 
bounds.

> In C99 there's no reason not to go the whole hog and write
>
>    int array_sum(int n, int (*data)[n]) { ... }

Possibly, if you're passing the length too.

> Now you *can* ask about sizeof *data, and even the usual ARRAY_SIZE
> macro trick will work[1].  Of course the answer will be n, so there's
> not much point, but then there was not much point in passing a pointer
> to an array in the first place!

Why not? If you want to access the array from inside the function, my 
point is it makes more sense, type-wise, to pass a pointer to the array, 
rather than a pointer to an int.

Because that pointer-to-int might point to an int in some array, but it 
can also point to an int anywhere else. And if you take the function 
definition in isolation (in some library for example), then you are only 
relying on comments to tell you the parameter is meant to be an array; 
it's not enforced by the language.

-- 
Bartc

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


Page 1 of 4  [1] 2 3 4  Next page →

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


csiph-web