Constant strings

Discussion in 'C Programming' started by BartC, Apr 18, 2014.

  1. BartC

    Kaz Kylheku Guest

    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.
    Or the non-scalar argument case of an array being passed using a "pointer to
    array"!
     
    Kaz Kylheku, Apr 29, 2014
    1. Advertisements

  2. 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.
     
    Ben Bacarisse, Apr 29, 2014
    1. Advertisements

  3. (snip, someone wrote)

    (snip, then I wrote)
    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.
    -- glen
     
    glen herrmannsfeldt, Apr 29, 2014
  4. 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>
     
    Ben Bacarisse, Apr 29, 2014
  5. BartC

    Kaz Kylheku Guest

    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.)
     
    Kaz Kylheku, Apr 29, 2014
  6. Yes, and even when the function is not inline. Some compilers are very
    clever.
    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.
     
    Ben Bacarisse, Apr 29, 2014
  7. BartC

    Kaz Kylheku Guest

    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?
     
    Kaz Kylheku, Apr 29, 2014
  8. (snip)
    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.
    -- glen
     
    glen herrmannsfeldt, Apr 29, 2014
  9. 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.
     
    Ben Bacarisse, Apr 29, 2014
  10. BartC

    Stefan Ram Guest

    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.
     
    Stefan Ram, Apr 29, 2014
  11. Call by name would be pretty hard just using macros. As far
    as I know, you need actual callable functions to do it.

    -- glen
     
    glen herrmannsfeldt, Apr 29, 2014
  12. BartC

    Kaz Kylheku Guest

    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.
     
    Kaz Kylheku, Apr 29, 2014
  13. (snip)
    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
     
    glen herrmannsfeldt, Apr 29, 2014
  14. 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.
     
    Malcolm McLean, Apr 29, 2014
  15. BartC

    Stefan Ram Guest

    Recursion can be implemented with linked activation records
    on a heap. (In an abstract sense, this is a stack, too.)
     
    Stefan Ram, Apr 29, 2014
  16. Yes, exactly. (I never thought I'd say that!)
     
    Ben Bacarisse, Apr 29, 2014
  17. 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.
     
    Malcolm McLean, Apr 29, 2014
  18. Then they're not C compilers (though they may be perfectly useful
    compilers for some C-like dialect).
     
    Keith Thompson, Apr 29, 2014
  19. (snip)
    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
     
    glen herrmannsfeldt, Apr 29, 2014
  20. BartC

    David Brown Guest

    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.
     
    David Brown, Apr 29, 2014
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.