From: David Thompson <dave.thompson2@verizon.net>
Subject: Re: Legit Warnings or not
Date: Thu, 04 Aug 2011 01:56:51 -0400
Date: 2011-08-04T01:56:51-04:00 [thread overview]
Message-ID: <3qbk3752jm6etp8kjrmq75i8vksaq84oqf@4ax.com> (raw)
In-Reply-To: 98vi3lFinkU1@mid.individual.net
On Sat, 23 Jul 2011 12:20:53 +0300, Niklas Holsti
<niklas.holsti@tidorum.invalid> wrote:
> Randy Brukardt wrote:
>
> > My point being that hidden pointers are extremely common in the
> > implementation of modern programming languages, and certainly are common in
> > Ada implementations. The only language I know of that insists on making such
> > things explicit is C, and I think even it has some cases where the pointers
> > are implicit (struct parameters).
>
> Continuing that parenthesis: struct parameters in C are passed by value
> unless you explicitly declare the parameters as pointers. I think the
Yes. Or at least as-if; it would be legal for an ABI to actually pass
a pointer to a copy used only by the callee, or to a value which the
callee copies-in, but I've never seen anyone do so.
> only implicit introduction of "pointer" in C is when a function
> parameter is declared as an array or a function, in which case the
> formal parameter type is actually a pointer to the declared type. Other
> rules let you omit the "address of" operator (&) on the actual parameters.
>
Nearly.
If you declare a parameter as a function type F, it is actually a
pointer-to-F. An expression which is a function name is implicitly
converted to a pointer to that function, which is the correct type to
pass to a pointer-to-F parameter, and if you write &f it also creates
the same pointer. The function-call operation f(x) actually takes a
pointer-to-F as its left operand, which could either be a 'decayed'
actual function or a stored pointer including a parameter. Thus
ptrf(x) calls the function ptrf points to; (*ptrf)(x) takes the target
of ptrf and re-forms a pointer and calls the same target; (**ptrf)(x)
takes the target, re-forms a pointer, derefences it, re-forms the
pointer again, and calls the same target, etc ad nauseam.
If you declare a parameter as an array type A with element E, it is
actually a pointer-to-E (not A). If an expression is an array lvalue
it is implicitly converted to a pointer to its first element, which is
the correct type to pass to pointer-to-E. Pointer-to-E doesn't 'know'
the array bound so void f (float x []) aka void f (float * x) can be
passed an array of float of any bound -- and the actual bound, or a
smaller used extent, must be passed or known by other means.
The subscript operation a[i] effectively takes a pointer-to-E.
Even more pedantic: subscripting in C is actually defined in terms of
pointer arithmetic: ptr +- integer yields a pointer moved up or down
by integer elements, usually integer*sizeof(element) bytes, and + is
commutative, and a[i] is _defined_ as *( (a) + (i) ), so actually i[a]
is equivalent to a[i], which was useful for early IOCCC entries.
But if you declare a parameter as pointer-to-array, that's a different
type that does know the bound (except if the bound is variable,
a new feature in C99) and not passable or assignable from a
pointer-to-element. In that case you must explicitly write &array
(where array is the correct size) to get a suitable argument value.
Or write a cast, but that's uglier and often less robust.
Note that strings in C are just array of char(acter), or wchar_t,
containing a null terminator; thus the literal "xyz" in an expression
yields a pointer to char. (In C++ it's at least pointer to const char,
but in C 20 years of code existed before const was invented.)
This is actually just a case of the general array-element-pointer
rules above, but it is a very common case that has no syntactic
indication of an array and thus tends to confuse people.
What _is_ often done and might easily be confused is for struct
_returns_ from functions in C to be implemented using a pointer.
Like all function return types, these are by-value in the abstract
semantics. But many C ABIs return primitive scalars (int, float, etc.)
in a register, which doesn't work for a (potentially) large struct.
So it is common for the call sequence to provide temp space -- which
it can because C struct layout and size is fixed -- and pass a hidden
pointer which the callee epilogue uses to store the return value,
which the caller then uses. It is also possible, but more confusing,
to use a hybrid scheme where a struct type that is small enough to fit
in the desired register, typically 4 or 8 bytes, is returned there,
and only larger structs use caller-created space and pointer.
The issue doesn't arise for arrays because C can't return an array --
only a pointer used to access an array (in memory) or a struct
_containing_ an array (of static bound) in which case see above.
next prev parent reply other threads:[~2011-08-04 5:56 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-20 22:30 Legit Warnings or not Anh Vo
2011-07-20 23:16 ` Robert A Duff
2011-07-21 18:43 ` Anh Vo
2011-07-23 0:26 ` Randy Brukardt
2011-07-23 14:26 ` Robert A Duff
2011-07-21 2:37 ` Jeffrey Carter
2011-07-21 9:50 ` Brian Drummond
2011-07-21 14:39 ` Dmitry A. Kazakov
2011-07-23 0:36 ` Randy Brukardt
2011-07-23 9:03 ` Dmitry A. Kazakov
2011-07-23 11:07 ` Simon Wright
2011-07-23 11:21 ` Dmitry A. Kazakov
2011-07-26 21:25 ` Randy Brukardt
2011-07-27 7:45 ` Dmitry A. Kazakov
2011-07-28 0:37 ` Randy Brukardt
2011-07-28 9:22 ` Dmitry A. Kazakov
2011-07-28 14:22 ` Robert A Duff
2011-07-28 14:41 ` Dmitry A. Kazakov
2011-07-28 15:10 ` Robert A Duff
2011-07-28 17:05 ` Dmitry A. Kazakov
2011-07-28 23:32 ` Randy Brukardt
2011-07-28 23:48 ` Randy Brukardt
2011-07-29 6:57 ` Simon Wright
2011-07-29 18:56 ` Jeffrey Carter
2011-07-30 0:13 ` Randy Brukardt
2011-07-29 7:41 ` Dmitry A. Kazakov
2011-07-30 0:17 ` Randy Brukardt
2011-07-30 8:27 ` Dmitry A. Kazakov
2011-08-01 22:12 ` Randy Brukardt
2011-08-02 10:01 ` Dmitry A. Kazakov
2011-08-02 21:30 ` Randy Brukardt
2011-08-03 9:01 ` Dmitry A. Kazakov
2011-08-03 20:35 ` Randy Brukardt
2011-08-04 8:11 ` Dmitry A. Kazakov
2011-08-05 23:57 ` Randy Brukardt
2011-08-06 8:23 ` Dmitry A. Kazakov
2011-08-08 21:30 ` Randy Brukardt
2011-07-23 14:32 ` Robert A Duff
2011-07-26 21:32 ` Randy Brukardt
2011-07-21 15:28 ` Adam Beneschan
2011-07-21 15:41 ` Robert A Duff
2011-07-21 20:12 ` Adam Beneschan
2011-07-23 0:31 ` Randy Brukardt
2011-07-21 17:40 ` Jeffrey Carter
2011-07-21 21:30 ` Brian Drummond
2011-07-21 21:54 ` Adam Beneschan
2011-07-22 10:16 ` Brian Drummond
2011-07-22 14:54 ` Adam Beneschan
2011-07-23 0:46 ` Randy Brukardt
2011-07-23 0:42 ` Randy Brukardt
2011-07-23 9:20 ` Niklas Holsti
2011-08-04 5:56 ` David Thompson [this message]
2011-07-23 9:24 ` Dmitry A. Kazakov
2011-07-23 12:36 ` Brian Drummond
2011-07-21 15:13 ` Robert A Duff
2011-07-23 0:52 ` Randy Brukardt
2011-07-23 14:48 ` Robert A Duff
2011-07-21 14:17 ` anon
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox