Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #380515 > unrolled thread
| Started by | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| First post | 2024-01-19 12:49 -0800 |
| Last post | 2024-01-22 22:05 +0000 |
| Articles | 5 — 4 participants |
Back to article view | Back to comp.lang.c
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-01-19 12:49 -0800
Re: Call to a function Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-01-22 03:27 +0000
Re: Call to a function Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-01-21 20:14 -0800
Re: Call to a function scott@slp53.sl.home (Scott Lurndal) - 2024-01-22 16:36 +0000
Re: Call to a function Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-01-22 22:05 +0000
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2024-01-19 12:49 -0800 |
| Subject | Re: Call to a function |
| Message-ID | <86bk9hjbey.fsf@linuxsc.com> |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> The code we're discussing was snipped at some point, so here it
>>> is again:
>>>
>>> int main(void) {
>>> int obj = 42;
>>> typedef void func(void);
>>> if (0) {
>>> func *fptr = (func*)&obj;
>>> fptr();
>>> }
>>> }
>>>
>>> It illustrates the issue that the standard does not define the behavior
>>> of a conversion from an object pointer type to a function pointer type
>>> (other than the special case of a null pointer constant), but does not
>>> make such conversion, expressed as a cast, a constraint violation.
>>>
>>> I asked: "On what basis do you think a conforming implementation may
>>> reject it?
>>
>> The code is not strictly conforming.
>>
>>> Do you see a syntax rule or constraint that it violates?
>>
>> No.
>>
>>> Do you see some other basis for rejecting it?"
>>
>> Yes. The conversion expression can be untranslatable on some
>> platforms. That means any such expression cannot be part of
>> a strictly conforming program.
>
> I disagree. A conforming implementation could implement a
> conversion of an object pointer to a function pointer that always
> yields a null pointer, or that yields a pointer whose representation
> is derived from the representation of the operand. The latter is
> typically done for pointer-to-integer or integer-to-pointer
> conversions with mismatched sizes (6.3.2.3 explicitly says that
> integers may be converted to pointers and vice versa).
>
> If, hypothetically, the standard said that an otherwise valid
> program containing a conversion of an object pointer to a function
> pointer type must be successfully translated, then compiler
> implementers could easily find a way to implement such conversions,
> even if the result is not useful. It is incorrect to claim that
> such a conversion expression may be "untranslatable".
What you mean by translatable is different from what I mean. Of
course it is possible to produce a sequence of bits that conforms
to the bit-level representation of a function pointer. The
problem is that it might not be possible to do that in a way that
is sensible, meaningful, or useful.
The contrast with converting between pointers and integers is
helpful here. Converting a pointer to an integer, even if the
integer type isn't as big as the pointer type, is always
potentially useful, because for example the integer could be used
as a hash function. Integers also have the nice property that
they are dense (not counting padding bits), so producing any old
integer value will never be problematic. (Yes I know about the
rule that if the value cannot be represented the behavior is
undefined, but I'm not talking about that.) Going the other
direction, an integer type whose size is large enough (and almost
always there are such types) can guarantee that converting a
pointer to an integer is invertible. There is a deeper principle
here: the addressing structures used in actual hardware use
integers as the basis for addresses. Converting between integers
and pointers always makes sense at some low level. An exception
to that rule is elaborate function pointers, which can use very
large structured values to represent a pointer to function. This
exception is the primary motivation for the C standard saying
that "The result [of converting a pointer to an integer] need not
be in the range of values of any integer type"; in such cases
the behavior is undefined but it is still always allowed to write
an expression asking for such conversions - it is only trying to
execute these expressions that causes a problem.
Note that the C standard reflects the distinction I'm making
here. The standard specifically specifies that integers may
be converted to pointers, and vice versa. The standard also
specifically specifies that object pointers may be converted to
other object pointers, and that function pointers may be
converted to other function pointers. The standard does NOT
specify that function pointers may be converted to object
pointers, or that object pointers may be converted to function
pointers. This difference corresponds exactly to what I mean
by translatable and untranslatable. This distinction is not
incidental, accidental, or meaningless. On the contrary, it is
certainly deliberate, and goes to the heart of the question here.
>> I have no interest in treating you as a student. I'd be much
>> happier if you would do more thinking for yourself.
>
> I would be happier if you would not assume that I'm not already
> doing that.
It's not assumption but observation. To give an example, not too
long ago you asked a question in comp.std.c asking about undefined
behavior and indeterminate answers. I wrote a long posting in
response, basically going through a thorough and systematic review
of the history in different versions of the C standard. I'm sure
you could have done that yourself if you had tried to do so.
Please note that I'm not saying that you *should* have done that,
only that you *could* have done that.
> Be less arrogant.
I don't think it's arrogant to think or to say that you are
more capable than your comments would otherwise indicate. If
anything it seems just the opposite, that I have a higher
impression of your abilities than might seem to be the case
to a casual reader.
[toc] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-01-22 03:27 +0000 |
| Message-ID | <uoknaf$j1rr$2@dont-email.me> |
| In reply to | #380515 |
On Fri, 19 Jan 2024 12:49:57 -0800, Tim Rentsch wrote: > An exception to that rule is elaborate > function pointers, which can use very large structured values to > represent a pointer to function. Real-world example: PowerPC/POWER, where a function reference is two addresses, one for the code and the other for, I think it’s called the GOT (“Global Object Table”). Every piece of code assumes its GOT register has been set up with the right value.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-01-21 20:14 -0800 |
| Message-ID | <877ck2atsn.fsf@nosuchdomain.example.com> |
| In reply to | #380608 |
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
> On Fri, 19 Jan 2024 12:49:57 -0800, Tim Rentsch wrote:
>> An exception to that rule is elaborate
>> function pointers, which can use very large structured values to
>> represent a pointer to function.
>
> Real-world example: PowerPC/POWER, where a function reference is two
> addresses, one for the code and the other for, I think it’s called the GOT
> (“Global Object Table”). Every piece of code assumes its GOT register has
> been set up with the right value.
According to <https://devblogs.microsoft.com/oldnewthing/20180816-00/?p=99505>:
Since each function requires its table of contents to be set
properly, a function pointer on PowerPC is not a pointer to the
first instruction. Instead, it’s a pointer to a structure
consisting of two pointers: The first pointer points to the
first instruction of the function, and the second pointer is
the table of contents for the function.
A quick experiment with a gcc powerpc cross-compiler
(powerpc-linux-gnu-gcc (Ubuntu 13.2.0-4ubuntu3) 13.2.0) indicates that
void* and function pointers are the same size, 4 bytes.
I suppose compilers *could* have used that two-pointer structure as the
representation of a function pointer. Possibly that would have broken
code that makes invalid assumptions about function pointer sizes.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2024-01-22 16:36 +0000 |
| Message-ID | <yQwrN.323726$p%Mb.65389@fx15.iad> |
| In reply to | #380608 |
Lawrence D'Oliveiro <ldo@nz.invalid> writes: >On Fri, 19 Jan 2024 12:49:57 -0800, Tim Rentsch wrote: > >> An exception to that rule is elaborate >> function pointers, which can use very large structured values to >> represent a pointer to function. > >Real-world example: PowerPC/POWER, where a function reference is two >addresses, one for the code and the other for, I think it’s called the GOT >(“Global Object Table”). Every piece of code assumes its GOT register has >been set up with the right value. That's called dynamic linking and is only used for inter-library function calls. Intralibrary and intraapplication function calls don't need the GOT (Global Offset Table), which is used by all modern Unix and Linux distributions to support dynamic linking.
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-01-22 22:05 +0000 |
| Message-ID | <uomori$tokp$1@dont-email.me> |
| In reply to | #380629 |
On Mon, 22 Jan 2024 16:36:46 GMT, Scott Lurndal wrote: > .. GOT (Global Offset Table) ... There had to be actual addresses in there somewhere though, did there not? Otherwise you would have to ask “offsets to what?”.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web