reference type for C

J

James Kuyper

On 05/24/2013 08:23 AM, Malcolm McLean wrote:
....
We need to establish that counting - knowing the names of the numbers and
the next one - isn't arithmetic. Which was disputed but now seems to have
been accepted (counting isn't "adding one").

Some have said that counting is just a more primitive aspect of
arithmetic than addition is, and I think their point of view makes at
least as much sense as yours, but that's not really the key point of
contention. The real issue is your insistence on associating array
subscripting with counting, and not with addition.
That accepted, is array[42] adding 42 to array, taking the result, and
dereferencing it, or going to the collection marked "array" and taking item
42?

The former, in my opinion, though the latter could be another way of
thinking about it, if you consider 42 as simply a label rather than a
number. However, it is a valid way of thinking about it only to the
extent that it is NOT associated with counting. Interpreting "taking
item 42" in a way that connects it with counting loses all contact with
hardware reality, actual compiler implementations, and the descriptions
used in the C standard. It might be a suitable way of thinking about an
array stored in serial access memory, rather than RAM, but that is
hardly the conventional way of implementing C arrays.
... Internally, somewhere, we're going to have to generate the address of
item 42 in the array, but at machine code level the address might well never
appear, it could just as easily be a base (probably not array) and an offset,
depending on the exact instruction set used.

Base+offset is addition, and therefore arithmetic, as I see it. In
contexts where an array has a fixed address, and is subscripted with a
compile-time constant, the compiler might generate instructions that
load the address directly into a suitable register, without performing
addition. However, that just means that the addition was performed at
compile time rather than run time - it's still addition. Either way, it
has nothing to do with counting, or at least it has nothing more to do
with counting than addition itself has to do with counting, and the
analogy is exact.
 
M

Martin Shobe

In all but three contexts (operand of &, sizeof, or _Alignof),
any array name appearing in an expression "decays" to a pointer to
the array's first element. There's nothing special about array
names in expressions that are arguments; the substitution is in no
way specific to function calls.

It is in some way specific to function calls.
IMO, your final sentence is sort of true if you squint real
hard and tilt your head to one side, but is mostly misleading.

Arrays are passed by reference. To say that "decaying to a pointer"
is not the same as being passed by reference is a distinction without
a difference. That this invisible-conversion-of-an-object-to-
reference occurs in some other contexts isn't really relevant.

// Function on
void mutate(int bar[])
{
bar[0] = 1; //
}

int foo[3] = {0}; // Foo is an array. It is not a pointer.
mod(foo); // mutate does modify a copy of foo, it modifies foo
printf("%d\n",foo[0]);

However you want to phrase it, that's the semantics of "foo was passed
by reference".
Sure you can say "Actually, the address of foo was passed by value",
but on a fundamental level *that's what pass by reference* means.

class myarr {
public:
int arr_[3];
};

void mutate_by_reference(myarr& x)
{
x.arr_[0] = 1; //
}

void mutate_by_value(myarr x)
{
x.arr_[0] = 1; //
}


Which of those has the same semantics as the C example?

Neither. And rather obviously so.

A more relevant comparison would be

#include <iostream>

typedef int bar_t[2];

void mutate(bar_t bar)
{
bar[0] = sizeof bar;
}

void mutate_by_reference(bar_t & bar)
{
bar[1] = sizeof bar;
}

int main()
{
bar_t foo;

mutate(foo);
mutate_by_reference(foo);

std::cout << "[0]: " << foo[0] << "\n[1]: " << foo[1] << std::endl;
}

which on my system produces

[0]: 4
[1]: 8

Martin Shobe
 
M

Malcolm McLean

On 05/24/2013 08:23 AM, Malcolm McLean wrote:

Base+offset is addition, and therefore arithmetic, as I see it. In
contexts where an array has a fixed address, and is subscripted with a
compile-time constant, the compiler might generate instructions that
load the address directly into a suitable register, without performing
addition. However, that just means that the addition was performed at
compile time rather than run time - it's still addition. Either way, it
has nothing to do with counting, or at least it has nothing more to do
with counting than addition itself has to do with counting, and the
analogy is exact.
A lot of processors have instructions of the form

set base_register offset_register value_register

one major motivation is to make it easier to write C compilers. Ultimately
you have to generate the address base_register + offset_register on the
address bus, but that's deep in the hardware.

However looking at the machine code is largely a distraction.

Think of a more typical bit code code that array[42] = x; Very commonly
you see code like this

for(i=0;i<N;i++)
array = x;

Now you can think of this as "set i to zero, add it to array, take the result,
dereference it, and set the value at that address to x, set i to one, add it to
array ... etc". But nobody does. Everybody, when asked to walk through or dry
run this code, says, "take the first element of array, set it to x, take the second element and set it x, and so on, until we get to N-1".

However if we write the code as

for(i=0;i<N;i++)
{
ptr = array + i;
*ptr = x;
}

Then people will walk through the code in the first manner. Now we're explicitly
taking the result.
A compiler might generate array + 0, array + 2 array +3 etc, or it might
generate array, array++, array++. That's not too relevant.
 
G

Geoff

Most people know off by heart that q comes after p in the alphabet.
But they've lost track by then of the index. So most people wouldn't say
that knowing q is the next one on after p is enough to constitute arithmetic.

The arithmetic of the alphabet is identical to the arithmetic of the
integers or any symbolic "system". There is an order to the symbols
and a weight assigned to them. This is the same arithmetic that allows
us to sort words such that anyone schooled in that system knows that
the word "air" comes before "ale" in the order of words. The system
may be executed "by rote" but there is a system. The rules of that
system are "encoded" into the hardware of a processor such that it is
consistent with our symbolic system.

abcdefg... ab ac ad...
0123456789 10 11...
0123456789ABCDEF 10 11...

All of these are symbolic systems with "arithmetical" rules that make
them logically consistent. A word like "air" is quantifiable as a
group of symbols in the numerical base of the alphabet and the fact we
call the system of manipulation of those groups "grammar" makes it no
less mathematical than "two plus three equals five" is the same as 2 +
3 = 5, only the symbols have changed, not the rules. It's these
"mathematical" rules that make cryptography possible.
 
G

Geoff

No, but, your claims to contrary not-withstanding, it's also completely
unrelated to both the theory and practice of array subscripting.
We need to establish that counting - knowing the names of the numbers and
the next one - isn't arithmetic. Which was disputed but now seems to have
been accepted (counting isn't "adding one").

That accepted, is array[42] adding 42 to array, taking the result, and
dereferencing it, or going to the collection marked "array" and taking item
42? Internally, somewhere, we're going to have to generate the address of
item 42 in the array, but at machine code level the address might well never
appear, it could just as easily be a base (probably not array) and an offset,
depending on the exact instruction set used.

I do not accept that counting is not arithmetic.

Definition:

The method or process of computation with figures: the most elementary
branch of mathematics.

The branch of mathematics dealing with the properties and manipulation
of numbers: "the laws of arithmetic".

Counting is manipulation of symbols according to the rules of the
system of mathematics, counting is arithmetic. Q.E.D.

The fact that the order of the numbers is written into your brain and
you can recite it from memory doesn't make it any less arithmetical.
It's the same inside a computer. However, where your brain might
extract the symbols and apply these rules seemingly without executing
them step by step a computer has to do it in sequence since those
rules are encoded into the hardware. See my post else-thread.
 
J

James Kuyper

On Friday, May 24, 2013 3:16:01 PM UTC+1, James Kuyper wrote: ....
one major motivation is to make it easier to write C compilers. Ultimately
you have to generate the address base_register + offset_register on the
address bus, but that's deep in the hardware.

However looking at the machine code is largely a distraction.

Looking at the machine code is precisely analogous in C, to looking at
the way people evaluate 3+42 to determine whether they're doing it by
counting or addition. If you don't look at the process, but only at the
final result, you can't tell the difference between calculating 3+42 by
counting, or by addition. Similarly, if you don't look at the machine
code, but only at the final result, then you can't tell the difference
between evaluating pointer++ 42 times or evaluating pointer+42.
It both cases, you could distinguish the algorithms used by also looking
at the amount of time that it takes, and see whether it increases
linearly. And if you do that with array subscripting, you will find that
evaluating array[n] does not take time that increases linearly with n,
is therefore NOT being implemented by executing pointer++ 42 times.
for(i=0;i<N;i++)
array = x;

Now you can think of this as "set i to zero, add it to array, take the result,
dereference it, and set the value at that address to x, set i to one, add it to
array ... etc". But nobody does. Everybody, when asked to walk through or dry
run this code, says, "take the first element of array, set it to x, take the second element and set it x, and so on, until we get to N-1".


That description might be given, but that's only because it's a
description that simply summarizes what goes when the subscript is
evaluated. Most people would simply leave that as an unanalyzed step,
but those who were competent to describe that step in more detail would
NOT describe array as incrementing a pointer initialized to point at
array, i times. They would describe it as adding i to such a pointer.

Your description more accurately fits the following loop:

int *end = array+N;
for(int *pi = array; pi < end; pi++)
*pi = x;

except insofar as it describes termination of the loop in terms of N
rather than 'end'. Of course, they both might be optimized to exactly
the same machine code.
 
M

Malcolm McLean

On Fri, 24 May 2013 05:23:58 -0700 (PDT), Malcolm McLean



I do not accept that counting is not arithmetic.



Definition:



The method or process of computation with figures: the most elementary
branch of mathematics.


The branch of mathematics dealing with the properties and manipulation
of numbers: "the laws of arithmetic".

Counting is manipulation of symbols according to the rules of the
system of mathematics, counting is arithmetic. Q.E.D.

The fact that the order of the numbers is written into your brain and
you can recite it from memory doesn't make it any less arithmetical.
It's the same inside a computer. However, where your brain might
extract the symbols and apply these rules seemingly without executing
them step by step a computer has to do it in sequence since those
rules are encoded into the hardware. See my post else-thread.
We know that q is the next one after p, but by this time we've lost track
of how far we are on in the sequence. We can't convert the index of q to
another number system, we can't draw q dots on the blackboard without
going "a b c ...".
So you could say that knowing the next one is a form of arithmetic, but
that's not how most people use the word.
 
G

Geoff

We know that q is the next one after p, but by this time we've lost track
of how far we are on in the sequence. We can't convert the index of q to
another number system, we can't draw q dots on the blackboard without
going "a b c ...".
So you could say that knowing the next one is a form of arithmetic, but
that's not how most people use the word.

Yes, that's true, but q dots is not q. My point is that the symbol q
is embedded in a system such that it has more "weight" than p but less
than r and that weight is derived from the arithmetic of the alphabet.
The order of the alphabet in a human brain is such that it obeys the
same rules as the order of the first ten integers but we don't
intrinsically apply those rules to those symbols because we regard
them as separate. But a computer CAN'T "think" that way because the
value assigned to the symbol q MUST be mathematical in origin.

I don't care how most people use the word. Most people are ignorant of
the fact their brains have been programmed with the rules of grammar
and the alphabet such that it is subconscious and they have forgotten
how they learned it.
 
K

Keith Thompson

Eric Sosman said:
In all but three contexts (operand of &, sizeof, or _Alignof),
any array name appearing in an expression "decays" to a pointer to
the array's first element. There's nothing special about array
names in expressions that are arguments; the substitution is in no
way specific to function calls.

_Alignof isn't an exception, since it can only take a parenthesized
type name, not an expression, as an operand. N1570 incorrectly lists
it as one of the exceptions, but the released 2011 ISO standard
corrects that. (This was discussed recently in comp.std.c, along
with the mostly unanswered question of *why* _Alignof can't take
an expression operand. The subject line was "Array operand of
_Alignof".)

The full rule (as you know) is that an expression of array type
decays to a pointer unless it's either the operand of unary "&",
the operand of "sizeof", or a string literal in an initializer used
to initialize an array object. The third case isn't an "array name".
 
K

Keith Thompson

gwowen said:
It is in some way specific to function calls.

No, it is in no way specific to function calls.

int arr[10];
int *ptr;
ptr = arr;
func(arr);

Exactly the same implicit conversion occurs in the assignment and in the
function call, and it occurs because an expression of array type appears
in a context other than one of the three exceptions ("&", "sizeof", and
a string literal used to initialize an array object).
Arrays are passed by reference. To say that "decaying to a pointer"
is not the same as being passed by reference is a distinction without
a difference. That this invisible-conversion-of-an-object-to-
reference occurs in some other contexts isn't really relevant.

The C language does not have pass by reference. It has pass by value.

In almost exactly the same sense, C does not have linked lists as a
built-in construct. You can implement the semantics of both
pass-by-reference and linked lists using pointers.

The main difference is that C has more syntactic sugar for dealing with
arrays.
// Function on
void mutate(int bar[])

The definition of bar takes advantage of a distinct language rule, that
a parameter declaration that looks like it's of array type is "adjusted"
so it's really of pointer type. The "decay" rule and the "adjustment"
rule are independent; the language could have had either one without the
other. (They do work together to allow the *appearance* of passing
arrays by reference, but it's only an appearance.)

The above is *exactly* equivalent to

void mutate(int *bar)
{
bar[0] = 1; //

The [] operator is defined to take two operands, a pointer and an
integer. It's yet another case of syntactic sugar designed to make it
look like you're operating directly on arrays.

You have to look past the syntactic sugar to understand what's really
going on.

In a language with true pass-by-reference, I'd argue that it's not
necessarily syntactic sugar for passing a pointer, since it's not
necessarily defined that way. In C, passing an array name to a function
that has what appears to be an array parameter *is* syntactic sugar,
since it's rigorously defined in terms of other constructs in the
language.
}

int foo[3] = {0}; // Foo is an array. It is not a pointer.
mod(foo); // mutate does modify a copy of foo, it modifies foo

(I think you meant "mutate(foo)", not "mod(foo)".)

Yes, it modifies the contents of foo because it passes the *address* of
foo's first element to mutate(), and uses the [] operand on that address
to modify data pointed to by the address.
printf("%d\n",foo[0]);

However you want to phrase it, that's the semantics of "foo was passed
by reference".
Sure you can say "Actually, the address of foo was passed by value",
but on a fundamental level *that's what pass by reference* means.
class myarr {
public:
int arr_[3];
};

void mutate_by_reference(myarr& x)
{
x.arr_[0] = 1; //
}

void mutate_by_value(myarr x)
{
x.arr_[0] = 1; //
}


Which of those has the same semantics as the C example?

Both, since none of the three examples has any visible behavior.

Ok, that's pedantic even for me.

Classes (C++ only) and structs (C and C++) are passed by value, with no
implicit pointer conversion. The mutate_by_reference function could be
written in C by passing a pointer to a struct. The mutate_by_value
function could be written in C just like the C++ version, and would have
the same semantics (it would modify a local copy).
 
K

Keith Thompson

James Kuyper said:
Why not? C has objects, and though the meaning of "object" is different
in C++ than in C, the difference is irrelevant to the feasibility of
using linked lists.

The definition of "object" is not significantly different in
C and C++. In C, an object is a "region of data storage in the
execution environment, the contents of which can represent values".
In C++, an object is a "region of storage", with a note "A function
is not an object, regardless of whether or not it occupies storage
in the way that objects do."

C++ programmers often use the word "object" in a narrower sense,
related to object-orientedness, but those are the definitions from
the respective ISO standards.
 
K

Keith Thompson

James Kuyper said:
Well, I think that all along Malcolm has been trying, with his words,
to describe sequential versus random access.

True - and how many C compilers use sequential access memory to store
arrays? It's not impossible that there might be some; doing things that
way wouldn't prohibit a conforming implementation. In principle, the
concept of virtual memory complicates the issue. But Malcolm is claiming
that array[42] is inherently what he (and apparently no one else) calls
"counting on" regardless of whether or not it's actually implemented in
some unconventional fashion. The conventional fashion is random access,
and the C standard's definition of what array subscripts mean is written
to accommodate the conventional way of implementing them - it is not
consistent which his concept of "counting on".

I can't be sure, but I don't think Malcolm is claiming anything
having to do with implementing arrays using sequential access,
or with array indexing being an O(n) operation.

His argument, I think, is that arr[42] is *conceptually* not an
arithmetic operation; rather it refers to the 42nd (well, 43rd)
element of the array arr.

I've worked in languages (Pascal, Ada, Perl) that have arrays
and indexing, but in which the defined semantics of arrays and
indexing have nothing to do with pointers. In such languages,
arr[42] is *defined* to refer to element 42 of the array; it's up
to the compiler to figure out how to do that.

And even in C, it's possible to do a fair amount of work with arrays
with that kind of mental model.

I don't think the "counting on" thing (a term Malcolm seems to
have invented) is relevant to that model. "Counting on" is about
incrementing values, determining what comes after another value.
The model of array indexing without arithmetic is about using a
number to specify a location within an array, without necessarily
performing any kind of arithmetic. It's about understanding ordinal
numbers as indices without having to think about addition.

Of course array indexing in C is *defined* in terms of pointer
arithmetic.

And independently of that, incrementing a number *is* an arithmetic
operation. Addition is repeated incrementing, multiplication is
repeated addition, and exponentation is repeated multiplication.
And they're all arithmetic.
 
K

Keith Thompson

Malcolm McLean said:
We need to establish that counting - knowing the names of the numbers and
the next one - isn't arithmetic. Which was disputed but now seems to have
been accepted (counting isn't "adding one").

I've seen no such consensus here. Several people, including myself,
continue to disagree with that assertion.
 
J

James Kuyper

On 05/24/2013 02:32 PM, Keith Thompson wrote:
....
I can't be sure, but I don't think Malcolm is claiming anything
having to do with implementing arrays using sequential access,
or with array indexing being an O(n) operation.

His argument, I think, is that arr[42] is *conceptually* not an
arithmetic operation; rather it refers to the 42nd (well, 43rd)
element of the array arr.

Yes, but the difference between counting on and addition, as he has
defined it in the context of integers, is entirely a matter of
implementation, not conceptions. Mathematician define the concept of
integer addition in terms of repeated application of the "successor of"
operation, corresponding exactly to Malcolm's "counting on", so the
distinction he's making is purely a matter of how addition is
implemented, not the conceptual basis for addition. That is why I find
it bizarre that he doesn't want us to look at how array subscripts are
actually implemented.
I've worked in languages (Pascal, Ada, Perl) that have arrays
and indexing, but in which the defined semantics of arrays and
indexing have nothing to do with pointers. In such languages,
arr[42] is *defined* to refer to element 42 of the array; it's up
to the compiler to figure out how to do that.

And even in C, it's possible to do a fair amount of work with arrays
with that kind of mental model.

I don't think the "counting on" thing (a term Malcolm seems to
have invented) is relevant to that model.

That, I can agree with, and is precisely my main point.
 
E

Eric Sosman

It is in some way specific to function calls.

In what way, exactly? Can you show *any* use of an array
name as a function argument that differs from the use of an
array name in, say, simple assignment or arithmetic?

void foo(int*);
int array[42], *ptr;

foo(array);
ptr = array;
foo(ptr);

foo(array + 3);
ptr = array + 3;
foo(ptr + 3);

ptr = array + 3;
foo(ptr);

After the declaration (which isn't an expression), every use of
`array' above becomes a pointer to the first element of the array,
in exactly the same manner. There is absolutely nothing special
about the function calls. (Note that there is only one foo(), not
one taking a pointer and another taking an array "by reference;"
C has no function overloading.)
Arrays are passed by reference. To say that "decaying to a pointer"
is not the same as being passed by reference is a distinction without
a difference. That this invisible-conversion-of-an-object-to-
reference occurs in some other contexts isn't really relevant.

Your claim is that arrays get special treatment in function
calls ("as part of the calling convention" was your phrase). When
shown that the exact same conversion happens in most other uses of
array names, you just say that's not "really relevant." In short,
the special treatment is "special" only because you say so, not
because it has any distinguishing characteristic.

"Well, isn't that SPECIAL?" -- Enid Strict
// Function on
void mutate(int bar[])
{
bar[0] = 1; //
}

int foo[3] = {0}; // Foo is an array. It is not a pointer.
mod(foo); // mutate does modify a copy of foo, it modifies foo

mutate() -- I guess that's what you meant here -- modifies
the int pointed to by its argument. Its argument is a pointer,
as you can demonstrate with

mutate(foo + 2);
or
mutate(&foo[1]);
or
int x;
mutate(&x);

Another illuminating demonstration would be to have mutate()
examine `sizeof bar', and then to call it with several arrays of
different lengths. The fact that mutate() will always get the same
sizeof no matter what array the caller provides (even if the caller
provides NULL!) should lead a reasonable person to doubt that an
"array reference" is in play here.
printf("%d\n",foo[0]);

However you want to phrase it, that's the semantics of "foo was passed
by reference".

Since this thread is in a C language forum and concerns a
suggested change to the C language, I "want to phrase it" in the
terms that define that language. The words "reference" and
"references" appear frequently in the C Standard, but never in
connection with function arguments or parameters. Not even once.
Sure you can say "Actually, the address of foo was passed by value",

No; I'd say "A pointer to foo[0] was passed by value."
but on a fundamental level *that's what pass by reference* means.

So C already has references, and this thread is vacuous?
class myarr {
[...]
Which of those has the same semantics as the C example?

Sorry; I don't do C++ unless I'm being paid, and even then
I do it grudgingly. (And badly.)
 
M

Malcolm McLean

And independently of that, incrementing a number *is* an arithmetic
operation. Addition is repeated incrementing, multiplication is
repeated addition, and exponentation is repeated multiplication.
And they're all arithmetic.
Counting isn't quite incrementing. Incrementing is adding the same
value each time (as you have used the term). Counting is going to the
next one. So we can go a, b, c ... without claiming that there is an
interval between a and b which is equal to that between b and c. We
can also go one, two, three ... We don't need to understand that there
is a difference between the two lists in order to count. We do need to
understand this in order to add.
 
E

Eric Sosman

_Alignof isn't an exception, since it can only take a parenthesized
type name, not an expression, as an operand. N1570 incorrectly lists
it as one of the exceptions, but the released 2011 ISO standard
corrects that. (This was discussed recently in comp.std.c, along
with the mostly unanswered question of *why* _Alignof can't take
an expression operand. The subject line was "Array operand of
_Alignof".)

Oops. Thanks!
The full rule (as you know) is that an expression of array type
decays to a pointer unless it's either the operand of unary "&",
the operand of "sizeof", or a string literal in an initializer used
to initialize an array object. The third case isn't an "array name".

I wrote "array name" precisely to rule out that case.
 
S

Seebs

We need to establish that counting - knowing the names of the numbers and
the next one - isn't arithmetic.

This might be true when teaching kindergarteners number, but it is absolutely
and totally unrelated to a discussion of the C programming language, in
which the term "arithmetic" has a strict meaning, which is unrelated to
this.
That accepted, is array[42] adding 42 to array, taking the result, and
dereferencing it,

Yes, that is exactly what it is, by formal definition. That's the point
of the specific statement that (a) is the same as (*(a+i)).

-s
 
S

Seebs

His argument, I think, is that arr[42] is *conceptually* not an
arithmetic operation; rather it refers to the 42nd (well, 43rd)
element of the array arr.

Yes.

And I think I now know why. I kept asking around, and finally found a
reference to that usage. Some teacher-training materials distinguish
between "counting" (1 to N), "counting on" (N to More Than N), and
"arithmetic". So a kid who has learned to get 5 + 3 by saying "five,
six, seven, eight" is "counting on" in this nomenclature.

With that terminology, "eighteen, nineteen, twenty, twenty-one" as a way
of establishing that 18+3 = 21 is "counting on", while doing 8+3, write
down a 1, carry a 1 to the next column, 1+1=2, is "arithmetic".

And then I guess his argument is that "fancy" things like, say,
computing a corresponding location in one string from a location
in another by doing something like:

new_tail = new + (old_tail - old);

is "arithmetic". But simply doing "x = a[42]" isn't, because there's
no need for an actual computation, you can just do it by starting at
a[0] and "counting on".

Which would be a thing which is sort of sensical from a standpoint of
how we would explain the process to people we thought might be preschool
or kindergarten age, but I can't see how it is particularly relevant
to the original context.

I went back and looked for that. The original context was a comment about
pointer arithmetic being risky, and references being a way to avoid them,
and he asserted (I'm paraphrasing here) that pointer arithmetic should
be avoided. Someone else asserted that array subscripting was pointer
arithmetic, and that's where we got this.

And with all *that* said:

I think he's got a point, but I disagree with pretty much all the specifics
of the expression of it. I don't think the "counting on" term is useful
or helpful. I don't think the distinction between "counting on" and
"arithmetic" has any relevance at all to this discussion. I don't think
it's at all reasonable to use a different field's terms of art when
discussing C, especially because the term "arithmetic", both as a noun
and as an adjective, is pretty firmly nailed down here.

Perhaps most crucially, if my memory of C++ is right, a reference to an
item in an array does not permit array subscripting, precisely because
array subscripting is a pointer-arithmetic kind of thing.

But he does have a good point: The sorts of things people describe as
"errors with pointer arithmetic" are generally not at issue in array
subscripting. "Errors in pointer arithmetic", to me, suggests something
like a fencepost error in computing the first character before or after
a given point, or trying to scan backwards through a string and
falling off the beginning of it, or whatever. In general, simple array
subscripting tends to omit these failures.

So, given the context of a discussion of ways in which references can
be useful even if you already had pointers, the assertion that references
are not subject to errors with pointer arithmetic, and that pointer
arithmetic can be risky, it is sort of reasonable to distinguish between
the sorts of fancy computation of derived pointer values (like the
new_tail example above) and mere array-subscripting, even though both
are clearly kinds of pointer arithmetic in a formal sense.

-s
 
J

James Kuyper

This might be true when teaching kindergarteners number, but it is absolutely
and totally unrelated to a discussion of the C programming language, in
which the term "arithmetic" has a strict meaning, which is unrelated to
this.

What is this "strict meaning" that you refer to?

The standard defines "arithmetic types" (6.2.5p18), "usual arithmetic
conversions" (6.3.1.8), and "arithmetic constant expression" (6.6p8). It
has a section (6.5.3.3) describing "Unary arithmetic operators", two
sections (7.3, 7.31.1) describing "Complex arithmetic", and another
(7.22.6) describing "Integer arithmetic functions". Annex F describes
"IEC 60559 floating-point arithmetic", Annex G describes "IEC
60559-compatible complex arithmetic", and Annex H describes "Language
independent arithmetic". It uses the phrase "pointer arithmetic" in
6.5.6p10, but doesn't define the phrase.

But I don't think the C standard ever defines the term "arithmetic" itself.

If the standard had bothered to describe a group of operators as the
"Binary arithmetic operators", I could use that to justify identifying
"pointer arithmetic" with the use of those operators on operands of
pointer type, which would match my own personal definition of "pointer
arithmetic". But the standard doesn't define any such group.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,060
Latest member
BuyKetozenseACV

Latest Threads

Top