reference type for C

G

glen herrmannsfeldt

Malcolm McLean said:
On 05/20/2013 04:36 AM, Malcolm McLean wrote:
I don't see the connection between your example of counting out
42 beans, and array[42].

Someone might be able to count beans, but not able to add.

You couldn't ask for 42+5 beans, but could ask for 42 beans,
then for five more, which they would count.

If you go to the bank to cash a check for $100, and ask for it
in $5 bills, they will count it out by fives. (5, 10, 15, 20 ...).
They could just count the 20 bills and multiply by five, but it
is tradition.
The defined behavior of array[42] does
not involve successively stepping through the first 42 positions
in the array; it's defined in terms of pointer addition, which in
turn is defined in terms of integer addition as applied to
positions within an array, something I'd consider to
unambiguously be "arithmetic".
Internally, yes, the processor will calculate 0x1234 + 42 to
give an address. But the programmer doesn't see that.

On many processors, the program has to compute the address
of array element 42, possibly as 0x1234+4*42. Note, though,
that VAX has an indexed addressing mode that includes the size
of the element being addressed. You can put 0x1234 in one
register, 42 in another, and get the appropriate array element.
He just sees "take array and go 42 positions to the right". Like
going to a street called array avenue and finding house 42.
That's counting on.
(Then normally you step through an array, you seldom see
array[42] = x in real code, it's almost always
for(i=0;i<42;i++)
array = x.
Very clearly this is counting on.)


Or maybe:

for(i=0;i<42;i++) *array++ = x;

(If array was a pointer variable, and its value wasn't needed again.)

-- glen
 
K

Keith Thompson

Malcolm McLean said:
Let's say I ask a primary school child to count out 42
beans, and he does it correctly. This is not sufficient to
be called "arithmetic". It's knowing the numbers, or "counting on".
It's also "counting on" if we don't start from one, lets say we
have a pile of beans, which we tell him contains a hundred, and
ask him to unite another pile of 42 beans to it, and he takes
beans from the 42 pile one by one and goes "a hundred and one,
and hundred and two ..."
That's not enough to be able to say that the child can do
simple arithmetic.

But let's say I ask him to count out forty two beans, count
out five, and then unite the piles and count them. This is
arithemetic. Because he's now taking two numbers, manipulating
them to produce a third, and storing the result.

Hmm.

I agree that counting or incrementing is not the same thing as
addition, and that the former is simpler than the latter.

I'd say that both are forms of arithmetic. Knowing how to count
doesn't imply that you know how to add -- nor does knowing how to
add imply that you know how to multiply or divide.
array[42] is counting on. ptr = array + 42 is arithmetic.

I *think* I see the distinction you're trying to make. I still
say it's neither valid nor meaningful.

There is a meaningful distinction between accessing array elements
using "array notation" (the "[]" operator) and accessing array
elements using explicit pointer arithmetic ("+" and "*"). The two
forms are by definition semantically equivalent, but they are in
some sense conceptually distinct -- especially for someone (like me,
for example) who first learned about array indexing in a language
that doesn't define it the way C does.

But I don't think that's quite what you're saying. As far as I can
tell, the point you're making requires ignoring a great many things.
 
J

James Kuyper

Exactly. "Counting on" is how people who haven't been to school add numbers.
It's a semantic argument whether you call it "arithmetic" or not, but generally
it's not considered to be so. It's the step before arithmetic.

So, if 3+42 is just "counting on", and not "arithmetic", what is
"arithmetic" (as you apply the term to ordinary numbers, outside of the
C context)?
So at primary school, they work with the intuitive method first. It's a new
pedagogical theory ...

"new"? I was taught using that method nearly a half-century ago. At that
time, the "new" teaching paradigm was not one that emphasized intuitive
approaches - it emphasized taking fundamental concepts, such as set
theory, that had previously only been taught to mathematicians in grad
school, and introducing them to everybody at a young age. I've no idea
whether using the "number line" was part of that movement - it's hard to
see as "advanced" something you were first introduced to at that young
of an age - which is, of course, the whole point of that approach.
 
G

glen herrmannsfeldt

(snip, someone wrote)
Mr Kuyper pointed out that the 'modern' C standard defines array to
*behave* as *(array+i), the fact is back then, array *was*
*(array+i). The array operator was merely short-hand. Underneath,
after the preprocessor, array became *(array + i ) which is
definitely 'arithmetic'. <g>

(snip)


(snip, then I wrote)
I don't see how that would necessarily affect the semantics of the []
operator, and it doesn't seem to be what ralph was referring to.

Yes, it doesn't affect the semantics.

But the people who started programming C on the PDP-11, and using
pointer arithmetic, especially the *s++ form, because it was
faster (and smaller) on the PDP-11.

(Also, the PDP-11 compilers probably weren't so good at optimizing
the [] form.)

Now, VAX has an indexed addressing mode that knows about the size,
such that one can index into an array without computing the address
(in a register or memory) of the array element. No idea how fast it
is, though.

The purpose of the comment was that what was optimal on the PDP-11
isn't necessarily optimal on later processors.

-- glen
 
R

roland.arthaud

Hey guys, why not talk about Peano's axioms ?
You are going off topic (haywire?) with the pointer arithmetic discussion.

I'd like the posts to stay on the following discussions :
- are some C++ features possible with C as is currently is ?
- would using a C++ compiler give unintended results on the C code

Also whenever you say : the code works the same whichever way,
I *hugely* favor the code that conspicuously shows one's intentions
(so yes for indexing and not playing with pointers, so yes for references
and not doing the same with pointers in the case of the alias)
- and let the optimizer do it's job.
 
J

James Kuyper

Hey guys, why not talk about Peano's axioms ?
You are going off topic (haywire?) with the pointer arithmetic discussion.

I'd like the posts to stay on the following discussions :

People will discuss what they want to discuss; there's not much that can
be done about that in an unmoderated newsgroup. Even in a moderated
newsgroup, thread drift is normal and considered acceptable, so long as
it stays within the range of topics that the newsgroup is appropriate
for. The meaning of "pointer arithmetic" (at least as it applies to C
code) is definitely on-topic for this newsgroup.
- are some C++ features possible with C as is currently is ?

Yes, but I wouldn't consider it likely. C still exists as a language
independent of C++ precisely because some people don't want it to
include very many C++ features.
- would using a C++ compiler give unintended results on the C code

Yes. Annex C of the C++ standard has a good summary of the possible
problems. Many of the possible problems involve a mandatory diagnostic,
which can be avoided just by paying attention to error messages while
compiling. Many of the others involve undefined behavior in one of the
two languages - the only reliable protection is to know precisely what
the issue is. However, it's also possible to write code which has
defined behavior in both languages, but it's different defined behavior
in each. The code that I posted was intended to include exactly one
instance of every such case. If you're interested in such issues, I'd
recommend attempting the "exercise for the student" that I mentioned at
the end of that message.
Also whenever you say : the code works the same whichever way,
I *hugely* favor the code that conspicuously shows one's intentions
(so yes for indexing and not playing with pointers, so yes for references
and not doing the same with pointers in the case of the alias)
- and let the optimizer do it's job.

In many contexts, pointers can show one's intentions just as clearly as
indexing arrays, and sometimes more clearly. Most of the str*() standard
libraries could, in principle, be written in strictly conforming C
(though they're likely to be implemented in assembler on many
platforms). That C code generally looks a lot cleaner if written to use
pointers rather than arrays.

In C++, the way operator overloading in supported makes the use of
references necessary. However, unless operator overloading is added to
C, the use of references rather than pointers does not (in my opinion)
greatly affect the ability to clearly show what the code is supposed to do.
 
M

Malcolm McLean

On 05/20/2013 12:04 PM, Malcolm McLean wrote:


So, if 3+42 is just "counting on", and not "arithmetic",
what is "arithmetic" (as you apply the term to ordinary
numbers, outside of the C context)?
Counting on is "start at three, and continue counting ...
now stop". If you conceptualise it as 3 + 42, you've made
the leap to arithmetic. People generally don't, they
count on as a consequence of knowing the numbers in their
native language, but they can't add values unless they
are explicitly taught.
 
I

Ian Collins

Malcolm said:
Counting on is "start at three, and continue counting ...
now stop". If you conceptualise it as 3 + 42, you've made
the leap to arithmetic. People generally don't, they
count on as a consequence of knowing the numbers in their
native language, but they can't add values unless they
are explicitly taught.

Which is one reason why young children a taught basic arithmetic using
number lines; they can conceptualise counting on (or back) N before they
understand add or subtract N.
 
G

glen herrmannsfeldt

(snip)
Counting on is "start at three, and continue counting ...
now stop". If you conceptualise it as 3 + 42, you've made
the leap to arithmetic. People generally don't, they
count on as a consequence of knowing the numbers in their
native language, but they can't add values unless they
are explicitly taught.

Or watch kids, not so long after they learn to count, they
can "add" by counting, and then "subtract" by counting backwards.
(As long as the numbers don't get too big.)

-- glen
 
G

glen herrmannsfeldt

(snip, someone wrote)
In many contexts, pointers can show one's intentions just as clearly as
indexing arrays, and sometimes more clearly. Most of the str*() standard
libraries could, in principle, be written in strictly conforming C
(though they're likely to be implemented in assembler on many
platforms). That C code generally looks a lot cleaner if written to use
pointers rather than arrays.

But mostly because we are used to seeing them that way:

while( *s++ = *t++) ;

or

for(i=0; t; i++) s=t;
s=0;

The latter is almost legal Java, and so almost understandable
by a Java programmer. Fortran programmers would also have an
easier time understanding it. If you consider [] as a
subscript operation, it is close to the way mathematicians
would see it.

Other than that many C compilers might have been designed to
special case the former, I don't know that one is necessarily
faster than the other on current processors.


-- glen
 
J

James Kuyper

Counting on is "start at three, and continue counting ...
now stop". If you conceptualise it as 3 + 42, you've made
the leap to arithmetic. People generally don't, they
count on as a consequence of knowing the numbers in their
native language, but they can't add values unless they
are explicitly taught.

So the difference between 3+42 as "counting on" and 3+42 as "arithmetic"
is entirely a matter of how the person implementing the operation thinks
about it? I doubt that there's any implementation of C, anywhere, where
array[42] is implemented in a fashion that corresponds to what you call
"counting on" rather than to arithmetic. Can you cite any?
 
R

roland.arthaud

People will discuss what they want to discuss; there's not much that can
be done about that in an unmoderated newsgroup. Even in a moderated
newsgroup, thread drift is normal and considered acceptable, so long as
it stays within the range of topics that the newsgroup is appropriate
for. The meaning of "pointer arithmetic" (at least as it applies to C
code) is definitely on-topic for this newsgroup.

James, you are right.
I cannot prevent people from rambling on the subject of what is or what is not arithmetic. At some point, to me it is nitpicking and not very useful for a news group on the C language - my opinion.

But if you want my pick on the subject ;-) : the discussion is somewhat missing the point. I think Malcom was in hindsight talking about behaviour vs implementation.

A compiler language only talks about behaviour.
In the discussion, I feel that people talk about the equivalence of indexing and pointer (arithmetic, arghh -no) usage, mostly because they "know" howit translates in machine code.

But it hinges on knowledge of one implementation.
Let me propose for the sake of the discussion that we set the stage in 500 years from now : quantum computing has come of age now.
For some reason (let's say because of particle spin or charm) memory organization has to spread out odd and even indexes to different "address space",or whatever. Now seeing indexing and an equivalent linear addressing is totally irrelevant. I know what indexing means, I don't know what pointer meddling means - but I have to have my favorite compiler of the time do the "right" thing : probably something defined in terms of (quantum) indexing, not in linear address you had in mind 500 years ago - the tables have turned.
 
M

Malcolm McLean

On 05/20/2013 06:36 PM, Malcolm McLean wrote:
So the difference between 3+42 as "counting on" and 3+42
as "arithmetic" is entirely a matter of how the person
implementing the operation thinks about it? I doubt that
there's any implementation of C, anywhere, where
array[42] is implemented in a fashion that corresponds to > what you call "counting on" rather than to arithmetic.
Can you cite any?
If array is on the stack, then a typical assembly listing
will have a pointer called stack top, which points to
one past the end of all local variables, often with a
bit of space for the function return address or other
bits and bats. An explict array reference would resolve
to stack top, minus the position, so if array is fifty
elements wide, it would be stack top minus (50 - 42).

But the calculation may never be done at the assembly
level. Since instruction sets are designed to give
C compilers an easy time, often there a special "base plus
offset" instruction. Internally in the chip the base and
the offset will be joined to form an address, but often
it's not by addition -base might always have the lower bits
clear, offsets might be restricted to the value of those
lower bits. So the base offset calculation is implemented
internally as a logical operation, not an addition,
which saves circuitry because you don't need a carry.

So really it's pretty hopeless to look at details of
implementation and say something about the source code,
the C programmer's view of the program and the chip's
view of it are different things.
 
B

BartC

A compiler language only talks about behaviour.
In the discussion, I feel that people talk about the equivalence of
indexing and pointer (arithmetic, arghh -no) usage, mostly because they
"know" how it translates in machine code.

But it hinges on knowledge of one implementation.
Let me propose for the sake of the discussion that we set the stage in 500
years from now : quantum computing has come of age now.
For some reason (let's say because of particle spin or charm) memory
organization has to spread out odd and even indexes to different "address
space", or whatever. Now seeing indexing and an equivalent linear
addressing is totally irrelevant. I know what indexing means, I don't know
what pointer meddling means - but I have to have my favorite compiler of
the time do the "right" thing : probably something defined in terms of
(quantum) indexing, not in linear address you had in mind 500 years ago -
the tables have turned.

The way the hardware works should be irrelevant; the model of pointer
arithmetic that C has should still work. Because that's how the language is
defined (indexing and pointer arithmetic *are* equivalent, because C says
so). It's the compiler's job to implement that model on whatever hardware is
available.

Of course, C was designed around the way computer memory has worked over the
last few decades; so possibly it won't be the best choice of language in 500
years' time.
 
R

roland.arthaud

The way the hardware works should be irrelevant; the model of pointer
arithmetic that C has should still work. Because that's how the language is
defined (indexing and pointer arithmetic *are* equivalent, because C says
so). It's the compiler's job to implement that model on whatever hardware is
available.

Of course, C was designed around the way computer memory has worked over the
last few decades; so possibly it won't be the best choice of language in 500
years' time.

I totally concur.
It's only pointer operation is not the same as memory address arithmetic.

I just wanted to show that in C people so easily cross from behavior to implementation, leading them to biased choices according to a perceived efficiency to the detriment of an adequate representation - again, let the compiler do the job.
 
J

James Kuyper

This is not about "garbage collection" (which C++ does not have any more
than C does - you need libraries or classes that support it if you want
garbage collection), or the lifetime of memory allocations (which is a
separate issue). C objects never "die" - they just fade away from lack
of use, and the compiler re-uses their space (registers, stack space,
etc.)

C objects have a lifetime, and the C standard defines very precisely
when that lifetime ends. It is not just a matter of "fading away from
lack of use" - though it is in fact the case that it's no longer
possible to use an object once it's lifetime has ended. The C standard
doesn't define a meaning for the term "die", but it seems reasonable to
me to use that term to refer to what happens when the lifetime of a C
object ends.
In C++, objects have a specific "point of death" - it is when their
destructor is called.

If an object has a non-trivial destructor, C++ rules define that the
lifetime of the object ends when that destructor starts executing.
Otherwise, it ends when storage for that object is no longer allocated,
which is essentially the same as the C rules. However, unless the
destructor is invoked explicitly, an implementation has considerable
freedom to delay execution of a destructor, so the point of death is not
as specific as you suggest, or at least no more specific than the point
of death for a C object.
 
J

James Kuyper

On 05/21/2013 04:44 AM, Malcolm McLean wrote:
....
If array is on the stack, then a typical assembly listing
will have a pointer called stack top, which points to
one past the end of all local variables, often with a
bit of space for the function return address or other
bits and bats. An explict array reference would resolve
to stack top, minus the position, so if array is fifty
elements wide, it would be stack top minus (50 - 42).

But the calculation may never be done at the assembly
level. Since instruction sets are designed to give
C compilers an easy time, often there a special "base plus
offset" instruction. Internally in the chip the base and
the offset will be joined to form an address, but often
it's not by addition -base might always have the lower bits
clear, offsets might be restricted to the value of those
lower bits. So the base offset calculation is implemented
internally as a logical operation, not an addition,
which saves circuitry because you don't need a carry.

So really it's pretty hopeless to look at details of
implementation and say something about the source code,
the C programmer's view of the program and the chip's
view of it are different things.

So, for ordinary numbers being added by people, the difference between
3+42 as "counting on" and 3+42 as "arithmetic" depends upon how the
person thinks about the process. However, for pointers being added by a
computer, array[42] is inherently "counting on", regardless of how the
computer implements it, even though the way that the computer handles it
has no meaningful similarity to the way human beings do "counting on"?

The definition of "counting on", combined with its claimed applicability
to array subscription, just gets less clear every time you add to the
explanation. You don't seem to be making any headway in convincing me
that the concept makes any sense, and I don't seem to be making any
headway in convincing you that it's nonsense, so I'm just going to give
up on this.
 
J

James Kuyper

On 05/21/2013 04:09 AM, (e-mail address removed) wrote:
....
James, you are right. I cannot prevent people from rambling on the
subject of what is or what is not arithmetic. At some point, to me it
is nitpicking and not very useful for a news group on the C language
- my opinion.

I find the nitpicking somewhat more interesting than your original
question, but then I'm well known for my pedantry. Most of the other
people monitoring this newsgroup seem to find both topics equally
uninteresting. You seem to think I'm distracting people from discussing
the topic you want to talk about. The fact that no one's talking about
your topic is due to the fact that no one monitoring this newsgroup is
interested in talking about it; my side issue has nothing to do with that.

....
A compiler language only talks about behaviour. In the discussion, I
feel that people talk about the equivalence of indexing and pointer
(arithmetic, arghh -no) usage, mostly because they "know" how it
translates in machine code.

But it hinges on knowledge of one implementation.

My understanding of what constitutes pointer arithmetic is grounded
entirely in the abstract definition of the language itself, and does not
depend in any way upon the implementation of that language. That seems
reasonable to me, since my understanding of what "arithmetic" means for
ordinary numbers is also grounded entirely in the abstract definitions
of mathematics, and does not depend in any way upon the specific symbol
manipulation processes that people use to implement arithmetic.

Malcolm's understanding does appear to depend upon the implementation,
but in ways that make no sense to me: implementation of array
subscription has never, as far as I know, ever been implemented in a way
that has any meaningful similarity to "counting on", as Malcolm defines
that term for ordinary numbers. It could be done; it wouldn't violate
any of C's requirements to do so; but it would make evaluation of
array[n] an O(n) process, and I can't imagine any reason why anyone
would want to do that when ways of implementing it in constant time are
well known.
 
M

Martin Shobe

C objects have a lifetime, and the C standard defines very precisely
when that lifetime ends. It is not just a matter of "fading away from
lack of use" - though it is in fact the case that it's no longer
possible to use an object once it's lifetime has ended. The C standard
doesn't define a meaning for the term "die", but it seems reasonable to
me to use that term to refer to what happens when the lifetime of a C
object ends.


If an object has a non-trivial destructor, C++ rules define that the
lifetime of the object ends when that destructor starts executing.
Otherwise, it ends when storage for that object is no longer allocated,
which is essentially the same as the C rules. However, unless the
destructor is invoked explicitly, an implementation has considerable
freedom to delay execution of a destructor, so the point of death is not
as specific as you suggest, or at least no more specific than the point
of death for a C object.
Can you give an example of when C++ has any freedom to delay invoking
a destructor that isn't an example of the "as if" rule?

Martin Shobe
 
J

James Kuyper

Can you give an example of when C++ has any freedom to delay invoking
a destructor that isn't an example of the "as if" rule?

The "as-if" rule often applies - actually making use of a C++ object
after it's lifetime has ended has undefined behavior, so the only things
that prevent a delay in execution of a destructor are any side-effects
it may cause. If all the destructor does is release resources (a common
case), the "as-if" rule allows it to be delayed almost indefinitely.

In any event, there is one case that does not rely on the "as-if" rule:
"The completions of the destructors for all initialized objects with
thread storage duration within that thread are sequenced before the
initiation of the destructors of any object with static storage
duration." (3.6.3p1) It could be a VERY long time between the end of any
particular thread and the time when objects with static storage duration
get destroyed.
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top