Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #73016 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2015-10-16 00:49 -0700 |
| Last post | 2015-10-17 13:59 -0700 |
| Articles | 20 on this page of 77 — 14 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-10-16 00:49 -0700 |
| Subject | Pointers, 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]
| From | Philip Lantz <prl@canterey.us> |
|---|---|
| Date | 2015-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Lew Pitcher <lew.pitcher@digitalfreehold.ca> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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