Constant strings


K

Kaz Kylheku

(snip on call by reference, or not)
Assignment to i resulting in changing a variable in the caller,
is a feature of "pass by transparent/invisible reference".
"Pass by explicit/visible reference" requires that a dereferencing
operator be applied to the reference to designate the caller's object
from which the reference was obtained.

So, the C [] operator is a visible dereference operator, but
the Fortran () (dummy array subscript) is not?

Ah, but in the case of arrays being passed around as a pointer
to the first element, this operator is used everywhere: by the
caller and callee alike.

It is not an operator which is inserted only in the called function
specifically to dereference the parameter.

Arrays in fact look like "pass by invisible reference". The invisibility comes
from the implicit array-to-pointer decay, and the way the array subscript works
on the reference just as well as on the array (so much so that all array
subscripting itself is defined that way). And further assisting the invisiblity
is that we can declare the function parameter using array syntax.

We call a function, giving the array as an argument: func(array).
In the function, we use the parameter as an array with subscripting,
and assignments to the element change the caller's array object.

It quacks almost like a duck, just with a slight goosey accent.
But C is different from Fortran in the need for * (or [0])
on scalar arguments.

Or the non-scalar argument case of an array being passed using a "pointer to
array"!
 
Ad

Advertisements

B

Ben Bacarisse

Kaz Kylheku said:
Kaz Kylheku said:
Kaz Kylheku wrote:
In C with pointers to array (the "other" way to pass the string by
reference):

void ptr2(char (*i)[5])
{
}

But that isn't really passing by reference as you have to dereference i
before using it as an array.

Since you have to take the address, and dereference the reference this
could be called "passing by visible reference". If you don't have to
then, that is "passing by transparent/invisible reference".

You could also call it "passing a pointer by value". Do you object to
that way of talking about it?

No; I don't object with any multiple non-conflicting views of the same system
or situation but rather to the denial of any of those views.

Calling passing a pointer by value "pass by reference" conflicts with my
view of the situation that used to be called "pass by reference". I can
fix that by simply flipping "by" to "a" when talking with a member of
the C-has-pass-by-reference party, but it does not help others who may
not know your party affiliation.
 
G

glen herrmannsfeldt

(snip, someone wrote)

(snip, then I wrote)
So, the C [] operator is a visible dereference operator, but
the Fortran () (dummy array subscript) is not?
Ah, but in the case of arrays being passed around as a pointer
to the first element, this operator is used everywhere: by the
caller and callee alike.
It is not an operator which is inserted only in the called function
specifically to dereference the parameter.
Arrays in fact look like "pass by invisible reference".
The invisibility comes from the implicit array-to-pointer decay,
and the way the array subscript works on the reference just as
well as on the array (so much so that all array subscripting
itself is defined that way). And further assisting the invisiblity
is that we can declare the function parameter using array syntax.
We call a function, giving the array as an argument: func(array).
In the function, we use the parameter as an array with subscripting,
and assignments to the element change the caller's array object.
It quacks almost like a duck, just with a slight goosey accent.

And one way it can quack slightly different is if you change
the local copy of the referece.

Now, if you make the reference itself const, not the values it
is refering to, then you pretty much have pass by reference.

I think you can also make a Java argument final, in which case
you also can't change the reference, but still change what
it refers to. Java final is stronger than C const, as, I believe,
you can't cast it away, and it is an error, not just a warning,
to try to change one.
But C is different from Fortran in the need for * (or [0])
on scalar arguments.
Or the non-scalar argument case of an array being passed
using a "pointer to array"!

-- glen
 
B

Ben Bacarisse

glen herrmannsfeldt said:
(snip)


I am not so sure what that means, but Fortran has much stricter
aliasing rules than C.

My point was that when a Fortran compiler is using call by reference, it
is not required to pass a pointer and then dereference it. That was the
claim Kaz made that I was replying to. In a fragment like this:

J = 99
CALL T(J)
...
SUBROUTINE T(I)
I = 42
END

the compiler can generate the same code (modulo the constant) for the
assignment to I as it does for the assignment to J. Some compilers
might pass an address then dereference it, but they are not required to
do that in all situations.

My remark "no more than any assignment does" is just a nod to the fact
that any assignment implicitly involves an indirect access, but there
need be no extra work simply because of the argument passing semantics.

<snip>
 
K

Kaz Kylheku

My point was that when a Fortran compiler is using call by reference, it
is not required to pass a pointer and then dereference it. That was the
claim Kaz made that I was replying to. In a fragment like this:

J = 99
CALL T(J)
...
SUBROUTINE T(I)
I = 42
END

the compiler can generate the same code (modulo the constant) for the
assignment to I as it does for the assignment to J. Some compilers
might pass an address then dereference it, but they are not required to
do that in all situations.

How about:

inline assign_42(int *i)
{
*i = 42;
}

assign_42(&x); /* generates the same code as x = 42: no pointer */

If T is an external function in a separately compiled module,
I don't see how Fortran can achieve it without a reference datum
being passed indicating the location of I.
(Or worse: call-by-name thunk or its ilk.)
 
B

Ben Bacarisse

Kaz Kylheku said:
How about:

inline assign_42(int *i)
{
*i = 42;
}

assign_42(&x); /* generates the same code as x = 42: no pointer */

Yes, and even when the function is not inline. Some compilers are very
clever.
If T is an external function in a separately compiled module,
I don't see how Fortran can achieve it without a reference datum
being passed indicating the location of I.
(Or worse: call-by-name thunk or its ilk.)

Neither can I (thought I would never second guess some clever linker
optimisation, especially given old Fortran's non-support of recursion).
I think we agree on the technicalities. Neither C nor Fortran require
passing an explicit pointer (even when it's explicit in the C code) and
there are situations in which neither of us can think of any reasonable
alternative for either language.

Trying to characterise a high-level language facility by what is
operationally required is, to my mind, unhelpful.
 
Ad

Advertisements

K

Kaz Kylheku

Trying to characterise a high-level language facility by what is
operationally required is, to my mind, unhelpful.

What's the difference between that and using an abstract machine model
which can be optimized?

If we are passing by reference, a reference (whatever that is) is operationally
required; that is fine, isn't it?
 
G

glen herrmannsfeldt

(snip)
My point was that when a Fortran compiler is using call by reference, it
is not required to pass a pointer and then dereference it. That was the
claim Kaz made that I was replying to. In a fragment like this:
J = 99
CALL T(J)
...
SUBROUTINE T(I)
I = 42
END
the compiler can generate the same code (modulo the constant) for the
assignment to I as it does for the assignment to J. Some compilers
might pass an address then dereference it, but they are not required to
do that in all situations.

The Fortran trandition was to compile each one separately, even
if they are in the same file. (Unlike C, with file scope variables.)

It might be, though, that more now optimize between routines,
such that they could consider that case.

It could also be fixed at link time.

The VAX/VMS compiler passes CHARACTER arguments by descriptor,
except that it also has to allow for passing a string constant
to a non-CHARACTER dummy argument (for Fortran 66 compatibility).
It does that by having the linker fix it, since the address is
the first part of the descriptor, it can replace the descriptor
address with the reference address at link time.
My remark "no more than any assignment does" is just a nod to the fact
that any assignment implicitly involves an indirect access, but there
need be no extra work simply because of the argument passing semantics.

-- glen
 
B

Ben Bacarisse

Kaz Kylheku said:
What's the difference between that and using an abstract machine model
which can be optimized?

If we are passing by reference, a reference (whatever that is) is
operationally required; that is fine, isn't it?

Yes, that's fine, but I don't think that was ever in doubt. That
passing by reference requires, in some abstract models, some form of
reference seems so uncontroversial that I can only assume that what you
said at some point seemed to me to be more than that. Otherwise, I can't
imagine why I commented. Anyway, I prefer to agree on this point than
to go back and try see why I disagreed.

On the matter of terminology, I am not persuaded that simply passing a
pointer should be called pass by reference. I realise that you won't be
persuaded, so we can just agree to differ.
 
S

Stefan Ram

Ben Bacarisse said:
On the matter of terminology, I am not persuaded that simply passing a
pointer should be called pass by reference. I realise that you won't be
persuaded, so we can just agree to differ.

It always refers to the /argument expression/. When the
argument value already is an address of an object o, as in

f( &o )

, then pass-by-reference would require a reference to »&o«
(not to »o«), because the argument expression is »&o« and
not »o«. C only has pass-by-value in function calls. Also
in »f( &o )«, the /value/ of »&o« is passed.

One can emulate some aspects of »call by reference« and
»call by name« using macros in C.
 
G

glen herrmannsfeldt

Stefan Ram said:
It always refers to the /argument expression/. When the
argument value already is an address of an object o, as in
, then pass-by-reference would require a reference to »&o«
(not to »o«), because the argument expression is »&o« and
not »o«. C only has pass-by-value in function calls. Also
in »f( &o )«, the /value/ of »&o« is passed.
One can emulate some aspects of »call by reference« and
»call by name« using macros in C.

Call by name would be pretty hard just using macros. As far
as I know, you need actual callable functions to do it.

-- glen
 
Ad

Advertisements

K

Kaz Kylheku

It always refers to the /argument expression/. When the
argument value already is an address of an object o, as in

f( &o )

, then pass-by-reference would require a reference to »&o«
(not to »o«), because the argument expression is »&o« and
not »o«. C only has pass-by-value in function calls. Also
in »f( &o )«, the /value/ of »&o« is passed.

We can easily talk, informally, about o being passed by reference (not &o, of course).

The variable o is the important value, and & is just a piece of "C fluff" to
get the called function to be able to update o.
 
G

glen herrmannsfeldt

(snip)
We can easily talk, informally, about o being passed by
reference (not &o, of course).
The variable o is the important value, and & is just a piece
of "C fluff" to get the called function to be able to update o.

Part of the design of VAX was standardized calling conventions,
including call by value, reference, and descriptor. (And at the
time that C was young.)

To override the default convention, you use %val(), %ref(),
or %descr() around the appropriate argument.

Seems to me, then, that VAX C should allow %ref(o) instead
of &o, though I never tried it.

Different fluff.

-- glen
 
M

Malcolm McLean

How about:

inline assign_42(int *i)

{

*i = 42;

}

assign_42(&x); /* generates the same code as x = 42: no pointer */

If T is an external function in a separately compiled module,
I don't see how Fortran can achieve it without a reference datum
being passed indicating the location of I.
(Or worse: call-by-name thunk or its ilk.)
Fortran 7 disallows recursion. So you don't need a stack.
In C, you do need a stack. There are also several situations in which the
assign by reference function will not be able to be replaced by a simple
assignment.
1) The function's address is taken. So the optimsing compiler has to
check the whole function first.
2) We've got a situation where the function is called with a pointer which
is assigned to a or b depending on some condition.
3) If the function is called with a null pointer. (Obviously you'd have to
not do the write in this situation. You can easily imagine a situation
where a human knows that the write can never happen, but a compiler can't
work it out).
4)If caller plays silly games, eg passing a pointer to a double to an int*.

But the main point is that in C the other arguments are going on the stack
anyway. So you've got to set up a stack pointer and push values onto it.
So most compiler writers will simply also take the pointer and push it on.
 
S

Stefan Ram

Malcolm McLean said:
In C, you do need a stack.

Recursion can be implemented with linked activation records
on a heap. (In an abstract sense, this is a stack, too.)
 
Ad

Advertisements

M

Malcolm McLean

Recursion can be implemented with linked activation records
on a heap. (In an abstract sense, this is a stack, too.)
Some small C compilers don't use stacks, and disallow recursion. They
also might restrict the number of parameters allowed in a function. But
basically you need a stack. Remember you've also got variadic functions
to support.
In Fortran you don't. There are no local copies of parameters, and the
call tree is defined.
 
K

Keith Thompson

Malcolm McLean said:
Some small C compilers don't use stacks, and disallow recursion.

Then they're not C compilers (though they may be perfectly useful
compilers for some C-like dialect).
 
G

glen herrmannsfeldt

(snip)
Some small C compilers don't use stacks, and disallow recursion. They
also might restrict the number of parameters allowed in a function. But
basically you need a stack. Remember you've also got variadic functions
to support.
In Fortran you don't. There are no local copies of parameters, and the
call tree is defined.

More specifically, many Fortran 66 and 77 compilers allocated
all variables statically. Some used static storage for the
return address.

The PDP-8 stores the return address in the first word of a subroutine,
then branches to the next word. Return is an indirect jump through
the first word. Works fine without recursion, but fails if the
program is in ROM.

-- glen
 
Ad

Advertisements

D

David Brown

Then they're not C compilers (though they may be perfectly useful
compilers for some C-like dialect).

On the compilers I have seen of this sort, they don't normally use
stacks and recursion is avoided when possible - but is not disallowed
completely. Stacks on chips like the 8051 are extremely inefficient for
data, so the compiler usually aims to use fixed memory addresses for
parameter passing and local data (the hardware stack is fine for return
addresses). On some such compilers, you need special pragmas or extra
keywords to allow a function to be recursive or re-entrant - then it is
not standard C since you need extra compiler-specific lines to get
standard re-entrant behaviour. On other compilers, the compiler can
figure out if a function is used recursively (or re-entrantly from
interrupts) and generate the software stack code only when strictly
needed. My guess is that such compilers are then standard C on that
particular point.

Typically such compilers stray from standard C on other issues, such as
lack of double-precision floating point (sometimes lack of
single-precision floats too), and perhaps lack of 32-bit integer types,
etc. They are, as you say, a C-like dialect.
 

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

Similar Threads


Top