public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* How to print pointer to function?
@ 2019-12-12  9:30 Josef Wolf
  2019-12-12  9:44 ` Jonathan Wakely
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Josef Wolf @ 2019-12-12  9:30 UTC (permalink / raw)
  To: gcc-help

Hello,

I would like to print the pointer to a function for debugging purposes.

But I keep getting a warning:

  ttt.c: In function 'insert_transfer':
  ttt.c:7:37: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
      7 |     printf ("lost transfer %p\r\n", (void*)rdyfunc);

Is there any way to get rid of this warning?

-- 
Josef Wolf
jw@raven.inka.de

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-12  9:30 How to print pointer to function? Josef Wolf
@ 2019-12-12  9:44 ` Jonathan Wakely
  2019-12-12  9:49 ` Liu Hao
  2019-12-17 13:01 ` Vincent Lefevre
  2 siblings, 0 replies; 17+ messages in thread
From: Jonathan Wakely @ 2019-12-12  9:44 UTC (permalink / raw)
  To: Josef Wolf, gcc-help

On Thu, 12 Dec 2019 at 09:30, Josef Wolf <jw@raven.inka.de> wrote:
>
> Hello,
>
> I would like to print the pointer to a function for debugging purposes.
>
> But I keep getting a warning:
>
>   ttt.c: In function 'insert_transfer':
>   ttt.c:7:37: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
>       7 |     printf ("lost transfer %p\r\n", (void*)rdyfunc);
>
> Is there any way to get rid of this warning?

Isn't it pretty clear the warning comes from -Wpedantic?

So don't use -Wpedantic (or the equivalent -pedantic).

If you want to write non-standard code without warnings, don't enable
pedantic warnings.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-12  9:30 How to print pointer to function? Josef Wolf
  2019-12-12  9:44 ` Jonathan Wakely
@ 2019-12-12  9:49 ` Liu Hao
  2019-12-12 11:00   ` Josef Wolf
  2019-12-17 13:01 ` Vincent Lefevre
  2 siblings, 1 reply; 17+ messages in thread
From: Liu Hao @ 2019-12-12  9:49 UTC (permalink / raw)
  To: Josef Wolf, gcc-help


[-- Attachment #1.1: Type: text/plain, Size: 738 bytes --]

在 2019/12/12 17:21, Josef Wolf 写道:
> Hello,
> 
> I would like to print the pointer to a function for debugging purposes.
> 
> But I keep getting a warning:
> 
>   ttt.c: In function 'insert_transfer':
>   ttt.c:7:37: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
>       7 |     printf ("lost transfer %p\r\n", (void*)rdyfunc);
> 
> Is there any way to get rid of this warning?
> 

Casting the point-to-function to `intptr_t` followed by `void*` will
silence the warning:

```
printf ("lost transfer %p\r\n", (void*)(intptr_t)rdyfunc);
```

This may also help if you attempt to cast between different types of
function pointers.


-- 
Best regards,
LH_Mouse


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-12  9:49 ` Liu Hao
@ 2019-12-12 11:00   ` Josef Wolf
  2019-12-17 12:56     ` Vincent Lefevre
  0 siblings, 1 reply; 17+ messages in thread
From: Josef Wolf @ 2019-12-12 11:00 UTC (permalink / raw)
  To: gcc-help

Thanks for the help, Liu!

This silenced the warning.

On Thu, Dec 12, 2019 at 05:49:17PM +0800, Liu Hao wrote:
> 在 2019/12/12 17:21, Josef Wolf 写道:
> > Hello,
> > 
> > I would like to print the pointer to a function for debugging purposes.
> > 
> > But I keep getting a warning:
> > 
> >   ttt.c: In function 'insert_transfer':
> >   ttt.c:7:37: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
> >       7 |     printf ("lost transfer %p\r\n", (void*)rdyfunc);
> > 
> > Is there any way to get rid of this warning?
> > 
> 
> Casting the point-to-function to `intptr_t` followed by `void*` will
> silence the warning:
> 
> ```
> printf ("lost transfer %p\r\n", (void*)(intptr_t)rdyfunc);
> ```
> 
> This may also help if you attempt to cast between different types of
> function pointers.
> 
> 
> -- 
> Best regards,
> LH_Mouse
> 




-- 
Josef Wolf
jw@raven.inka.de

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-12 11:00   ` Josef Wolf
@ 2019-12-17 12:56     ` Vincent Lefevre
  2019-12-17 13:17       ` Liu Hao
  2019-12-17 13:22       ` Segher Boessenkool
  0 siblings, 2 replies; 17+ messages in thread
From: Vincent Lefevre @ 2019-12-17 12:56 UTC (permalink / raw)
  To: gcc-help; +Cc: Josef Wolf

On 2019-12-12 11:53:05 +0100, Josef Wolf wrote:
> Thanks for the help, Liu!
> 
> This silenced the warning.

The goal should not be to silence warnings, but to write portable
code. If you find a way to silence a warning, only to silence a
warning, this is useless. You'd better disable warnings.

Here your code is still non-portable, perhaps *more* non-portable,
as only conversions between intptr_t and void * are guaranteed to
work. Moreover, the intptr_t type is optional.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-12  9:30 How to print pointer to function? Josef Wolf
  2019-12-12  9:44 ` Jonathan Wakely
  2019-12-12  9:49 ` Liu Hao
@ 2019-12-17 13:01 ` Vincent Lefevre
  2 siblings, 0 replies; 17+ messages in thread
From: Vincent Lefevre @ 2019-12-17 13:01 UTC (permalink / raw)
  To: Josef Wolf, gcc-help

On 2019-12-12 10:21:16 +0100, Josef Wolf wrote:
> I would like to print the pointer to a function for debugging purposes.
> 
> But I keep getting a warning:
> 
>   ttt.c: In function 'insert_transfer':
>   ttt.c:7:37: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
>       7 |     printf ("lost transfer %p\r\n", (void*)rdyfunc);
> 
> Is there any way to get rid of this warning?

The only portable & standard way I can think of is to store the
function pointer as an array of unsigned char, and output the
contents of this array. Note that there are no aliasing issues.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 12:56     ` Vincent Lefevre
@ 2019-12-17 13:17       ` Liu Hao
  2019-12-17 13:27         ` Segher Boessenkool
  2019-12-17 14:52         ` Vincent Lefevre
  2019-12-17 13:22       ` Segher Boessenkool
  1 sibling, 2 replies; 17+ messages in thread
From: Liu Hao @ 2019-12-17 13:17 UTC (permalink / raw)
  To: gcc-help, Josef Wolf

在 2019/12/17 20:56, Vincent Lefevre 写道:
> On 2019-12-12 11:53:05 +0100, Josef Wolf wrote:
>> Thanks for the help, Liu!
>>
>> This silenced the warning.
> 
> The goal should not be to silence warnings, but to write portable
> code. If you find a way to silence a warning, only to silence a
> warning, this is useless. You'd better disable warnings.
> 
> Here your code is still non-portable, perhaps *more* non-portable,
> as only conversions between intptr_t and void * are guaranteed to
> work. Moreover, the intptr_t type is optional.
> 

POSIX requires casting between `void*` and pointer-to-function to
preserve values in the specification of `dlsym()`. C++ says it is
conditionally supported. I don't see portability issues. Non-POSIX
systems (other than Windows) died decades ago.

-- 
Best regards,
LH_Mouse

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 12:56     ` Vincent Lefevre
  2019-12-17 13:17       ` Liu Hao
@ 2019-12-17 13:22       ` Segher Boessenkool
  2019-12-17 15:23         ` Vincent Lefevre
  2019-12-17 15:27         ` Manfred
  1 sibling, 2 replies; 17+ messages in thread
From: Segher Boessenkool @ 2019-12-17 13:22 UTC (permalink / raw)
  To: gcc-help, Josef Wolf

On Tue, Dec 17, 2019 at 01:56:48PM +0100, Vincent Lefevre wrote:
> On 2019-12-12 11:53:05 +0100, Josef Wolf wrote:
> > Thanks for the help, Liu!
> > 
> > This silenced the warning.
> 
> The goal should not be to silence warnings, but to write portable
> code. If you find a way to silence a warning, only to silence a
> warning, this is useless. You'd better disable warnings.
> 
> Here your code is still non-portable, perhaps *more* non-portable,
> as only conversions between intptr_t and void * are guaranteed to
> work. Moreover, the intptr_t type is optional.

Any object pointer, sure (since you can convert those to pointer to
void and back again).

Is there *any* portable way to print function pointers?  Other than
accessing it as bytes :-)


Segher

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 13:17       ` Liu Hao
@ 2019-12-17 13:27         ` Segher Boessenkool
  2019-12-17 14:52         ` Vincent Lefevre
  1 sibling, 0 replies; 17+ messages in thread
From: Segher Boessenkool @ 2019-12-17 13:27 UTC (permalink / raw)
  To: Liu Hao; +Cc: gcc-help, Josef Wolf

On Tue, Dec 17, 2019 at 09:17:20PM +0800, Liu Hao wrote:
> POSIX requires casting between `void*` and pointer-to-function to
> preserve values in the specification of `dlsym()`. C++ says it is
> conditionally supported. I don't see portability issues. Non-POSIX
> systems (other than Windows) died decades ago.

Not all systems are hosted at all.  Other than that I agree for anything
practical (and almost all embedded systems will have POSIX behaviour for
many basic things like this).


Segher

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 13:17       ` Liu Hao
  2019-12-17 13:27         ` Segher Boessenkool
@ 2019-12-17 14:52         ` Vincent Lefevre
  1 sibling, 0 replies; 17+ messages in thread
From: Vincent Lefevre @ 2019-12-17 14:52 UTC (permalink / raw)
  To: Liu Hao; +Cc: gcc-help, Josef Wolf

On 2019-12-17 21:17:20 +0800, Liu Hao wrote:
> POSIX requires casting between `void*` and pointer-to-function to
> preserve values in the specification of `dlsym()`. C++ says it is
> conditionally supported. I don't see portability issues. Non-POSIX
> systems (other than Windows) died decades ago.

If this were the case, why hasn't this changed in the C standard?

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 13:22       ` Segher Boessenkool
@ 2019-12-17 15:23         ` Vincent Lefevre
  2019-12-17 15:27         ` Manfred
  1 sibling, 0 replies; 17+ messages in thread
From: Vincent Lefevre @ 2019-12-17 15:23 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: gcc-help, Josef Wolf

On 2019-12-17 07:22:04 -0600, Segher Boessenkool wrote:
> On Tue, Dec 17, 2019 at 01:56:48PM +0100, Vincent Lefevre wrote:
> > Here your code is still non-portable, perhaps *more* non-portable,
> > as only conversions between intptr_t and void * are guaranteed to
> > work. Moreover, the intptr_t type is optional.
> 
> Any object pointer, sure (since you can convert those to pointer to
> void and back again).

Yes, but to be safe, you need to use void * as an intermediate type
in the conversion.

BTW, this does not mean that the conversion is lossless, as I suppose
that a pointer type may carry more information than just the address
of the object. But I think that this does not matter here.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 13:22       ` Segher Boessenkool
  2019-12-17 15:23         ` Vincent Lefevre
@ 2019-12-17 15:27         ` Manfred
  2019-12-17 16:30           ` Vincent Lefevre
  1 sibling, 1 reply; 17+ messages in thread
From: Manfred @ 2019-12-17 15:27 UTC (permalink / raw)
  To: gcc-help



On 12/17/2019 2:22 PM, Segher Boessenkool wrote:
> On Tue, Dec 17, 2019 at 01:56:48PM +0100, Vincent Lefevre wrote:
>> On 2019-12-12 11:53:05 +0100, Josef Wolf wrote:
>>> Thanks for the help, Liu!
>>>
>>> This silenced the warning.
>>
>> The goal should not be to silence warnings, but to write portable
>> code. If you find a way to silence a warning, only to silence a
>> warning, this is useless. You'd better disable warnings.
>>
>> Here your code is still non-portable, perhaps *more* non-portable,
>> as only conversions between intptr_t and void * are guaranteed to
>> work. Moreover, the intptr_t type is optional.
> 
> Any object pointer, sure (since you can convert those to pointer to
> void and back again).
> 
> Is there *any* portable way to print function pointers?  Other than
> accessing it as bytes :-)

n1570 section 6.3.2.3 p6 says "Any pointer type may be converted to an 
integer type. Except as previously specified, the result is 
implementation-defined. ..."

It says implementation-defined, not undefined, so AFAIU it is legal, 
although you can't make assumptions on the actual value of the result.

However, 7.20.1.4 specifies intptr_t and uintptr_t for pointers to void 
only, and 6.3.2.3 p1 specifies the conversion to/from pointers to void 
and pointers to "any object type" which does not include functions, AFAIU.
So, unless I am missing something, there seems indeed to be a broken 
link in the chain from pointer to function to (u)intptr_t.
But then what's the purpose of 6.3.2.3 p6 ?


> 
> 
> Segher
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 15:27         ` Manfred
@ 2019-12-17 16:30           ` Vincent Lefevre
  2019-12-17 22:49             ` Segher Boessenkool
  2019-12-18  2:39             ` Liu Hao
  0 siblings, 2 replies; 17+ messages in thread
From: Vincent Lefevre @ 2019-12-17 16:30 UTC (permalink / raw)
  To: gcc-help

On 2019-12-17 16:27:28 +0100, Manfred wrote:
> On 12/17/2019 2:22 PM, Segher Boessenkool wrote:
> > Is there *any* portable way to print function pointers?  Other than
> > accessing it as bytes :-)
> 
> n1570 section 6.3.2.3 p6 says "Any pointer type may be converted to an
> integer type. Except as previously specified, the result is
> implementation-defined. ..."
> 
> It says implementation-defined, not undefined,

IMHO, the difference matters mainly for the implementer: in short,
he must not ignore the issue. But an implementation-defined behavior
(or result) can be almost as useless as undefined behavior.

> so AFAIU it is legal, although you can't make assumptions on the
> actual value of the result.
> 
> However, 7.20.1.4 specifies intptr_t and uintptr_t for pointers to void
> only, and 6.3.2.3 p1 specifies the conversion to/from pointers to void and
> pointers to "any object type" which does not include functions, AFAIU.
> So, unless I am missing something, there seems indeed to be a broken link in
> the chain from pointer to function to (u)intptr_t.
> But then what's the purpose of 6.3.2.3 p6 ?

I would have actually preferred undefined behavior with a diagnostic.
I'm wondering why a programmer would want to convert a pointer to an
integer (except as a workaround to bizarre limitations, which would
better be solved directly by the standard).

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 16:30           ` Vincent Lefevre
@ 2019-12-17 22:49             ` Segher Boessenkool
  2019-12-18  2:39             ` Liu Hao
  1 sibling, 0 replies; 17+ messages in thread
From: Segher Boessenkool @ 2019-12-17 22:49 UTC (permalink / raw)
  To: gcc-help

On Tue, Dec 17, 2019 at 05:30:01PM +0100, Vincent Lefevre wrote:
> On 2019-12-17 16:27:28 +0100, Manfred wrote:
> > It says implementation-defined, not undefined,
> 
> IMHO, the difference matters mainly for the implementer: in short,
> he must not ignore the issue. But an implementation-defined behavior
> (or result) can be almost as useless as undefined behavior.

Thankfully GCC documents it as working as you expect.  All sane
implementations on sane platforms do, as far as I know (work, that is; I
have no idea how much they document).

Almost all useful programs are not strictly conforming anyway, so that't
alright.  It's not a bad idea to document what implementation-defined
behaviours your programs depend on, of course :-)

> I would have actually preferred undefined behavior with a diagnostic.
> I'm wondering why a programmer would want to convert a pointer to an
> integer (except as a workaround to bizarre limitations, which would
> better be solved directly by the standard).

There are many reasons.  Of course there are also many ways to abuse
this :-)

A very simple example is tagged pointers: put some value in the normally
unused high or low bits of a pointer, indicating whatever you want it to
indicate.  In C, you cannot do this in a pointer, but you *can* do it in
an uintptr_t (and after masking the tag out again, you can convert it
back to a pointer).


Segher

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-17 16:30           ` Vincent Lefevre
  2019-12-17 22:49             ` Segher Boessenkool
@ 2019-12-18  2:39             ` Liu Hao
  2019-12-18 10:05               ` David Brown
  1 sibling, 1 reply; 17+ messages in thread
From: Liu Hao @ 2019-12-18  2:39 UTC (permalink / raw)
  To: gcc-help

在 2019/12/18 上午12:30, Vincent Lefevre 写道:
> On 2019-12-17 16:27:28 +0100, Manfred wrote:
>> On 12/17/2019 2:22 PM, Segher Boessenkool wrote:
>>> Is there *any* portable way to print function pointers?  Other than
>>> accessing it as bytes :-)
>>
>> n1570 section 6.3.2.3 p6 says "Any pointer type may be converted to an
>> integer type. Except as previously specified, the result is
>> implementation-defined. ..."
>>
>> It says implementation-defined, not undefined,
> 

There's an enormous number of implementation-defined things, which
people kind of rely on to write 'portable code':

0. Conversion a value from `unsigned int` to `signed char` which doesn't
   fit in it yields an implementation-defined result.
   [C++14 now requires 2's complement, which is required by GCC.]
1. Shifting a negative integer to the right yields an impl-def result.
   Shifting a negative integer to the left is undefined behavior.
   [Ditto.]
2. Calling `fflush()` on an input stream results in undefined behavior.
   [The behavior is defined by POSIX 2008.]
3. Comparing two pointers that do not point to elements or past-the-end
   position of the same array, using one of <, >, <= or >= operators,
   results in undefined behavior.
   [C++ says the result is unspecified.]

So how can you write 'portable code' without regard to these facts?

In addition, even if it could be 'portable' to have standard casts
between `void*` and function pointers, the `%p` specifier of `printf()`
is still impl-def. So how can you make such combination more 'portable'?


-- 
Best regards,
LH_Mouse

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-18  2:39             ` Liu Hao
@ 2019-12-18 10:05               ` David Brown
  2019-12-18 11:12                 ` Segher Boessenkool
  0 siblings, 1 reply; 17+ messages in thread
From: David Brown @ 2019-12-18 10:05 UTC (permalink / raw)
  To: Liu Hao, gcc-help

On 18/12/2019 03:39, Liu Hao wrote:
> 脭脷 2019/12/18 脡脧脦莽12:30, Vincent Lefevre 脨麓碌脌:
>> On 2019-12-17 16:27:28 +0100, Manfred wrote:
>>> On 12/17/2019 2:22 PM, Segher Boessenkool wrote:
>>>> Is there *any* portable way to print function pointers?  Other than
>>>> accessing it as bytes :-)
>>>
>>> n1570 section 6.3.2.3 p6 says "Any pointer type may be converted to an
>>> integer type. Except as previously specified, the result is
>>> implementation-defined. ..."
>>>
>>> It says implementation-defined, not undefined,
>>
> 
> There's an enormous number of implementation-defined things, which
> people kind of rely on to write 'portable code':

It's entirely possible to write portable code that relies on
implementation-dependent behaviour.  The code can work correctly on
different systems, but perhaps with different results.  Sometimes you
have to have conditional compilation or similar tricks to get things to
work as needed.  In practice, often you can write code that is portable
to any "reasonable" implementation, and accept that the code won't work
for other systems:

#include <limits.h>
#if -INT_MAX == INT_MIN
#error Only two's complement signed integers supported by this code
#endif

Checking for lack of padding bits can be done too, I believe.


> 
> 0. Conversion a value from `unsigned int` to `signed char` which doesn't
>    fit in it yields an implementation-defined result.
>    [C++14 now requires 2's complement, which is required by GCC.]

IIRC it is C++20 that limits the signed integer representation to two's
complement.  Prior to that, I think C++ is actually more flexible than C
in the standards - but I don't think there are any known C++
implementations that are /not/ two's complement.  (The few remaining
ones' complement and signed magnitude C compilers are dinosaurs.)

Note that it is entirely possible for an implementation to have two's
complement representation but /not/ use modulo to reduce a value to fit
into a smaller signed type.  In particular, a compiler could choose to
raise a signal and halt with an error message (I don't know if any of
gcc's sanitizers do that).  But AFAIUI with C++20, and C20, such an
option would be non-conforming.

It is quite possible to write code for such conversions that is
portable.  This will handle most cases:

#include <limits.h>

signed char conv_uint_to_schar(unsigned int x) {
    unsigned int y = x % (UCHAR_MAX + 1);
    if (y <= SCHAR_MAX) return y;
    int z = (int) y - (SCHAR_MAX - SCHAR_MIN + 1);
    return z;
}

I think it will work with ones' complement and signed magnitude, and
with two's complement implementations with different conversion
behaviour.  (It does not cover compilers where "char" and "int" are the
same size, which is actually more realistic than different signed
integer representations.)  And gcc complies this to the same single
"mov" instruction that it uses for an implicit conversion.

> 1. Shifting a negative integer to the right yields an impl-def result.
>    Shifting a negative integer to the left is undefined behavior.
>    [Ditto.]

Many coding standards ban bit-manipulation operations (shifts and
bitwise operators) on signed types.  Stick to unsigned types and the
code is much more portable - and usually makes more sense.

> 2. Calling `fflush()` on an input stream results in undefined behavior.
>    [The behavior is defined by POSIX 2008.]

Implementations can always define the behaviour for things that are
undefined in the standards.  This is not an example of
implementation-defined behaviour, but of behaviour defined in additional
standards.  That is common in C (indeed in all programming).  If your
code relies on POSIX features, you can make it portable across POSIX
systems - but it will not be portable to non-POSIX systems.

> 3. Comparing two pointers that do not point to elements or past-the-end
>    position of the same array, using one of <, >, <= or >= operators,
>    results in undefined behavior.

So don't do that.  (This does mean that you can't implement functions
like memmove efficiently in portable, standards-only C.)

There are processors with C compilers where there are different memory
spaces, and it really does not make sense to compare pointers to them.
gcc supports at least one such device (the AVR).  There are also
processors where memory pointers and comparison can be complicated, such
as segmented x86 memory models.

On most systems, you can convert the pointers to "uintptr_t" and compare
those.  This will work correctly, to the extent that the comparison
makes sense, on any system which implements uintptr_t.

>    [C++ says the result is unspecified.]

That can sometimes make more sense, but it still won't let you write
memmove.

> 
> So how can you write 'portable code' without regard to these facts?
> 

No problem - don't use any of these features.

Portability only makes sense for some kinds of code - and even then, it
usually means "portable across similar systems".  The smallest system I
have programmed using gcc had 2 KB of program memory space and no ram at
all.  What kind of code would need to be portable from such a device, to
PC's, supercomputers, and forty year old mainframes?

When you write some code, you first figure out what the code should do.
 Then you can think about what range of systems it makes sense to
support.  Portable coding is then usually fairly easy as long as the
target range is sensible.

> In addition, even if it could be 'portable' to have standard casts
> between `void*` and function pointers, the `%p` specifier of `printf()`
> is still impl-def. So how can you make such combination more 'portable'?
> 
> 

The details of pointers is /always/ going to be implementation specific,
since pointers are implemented in different ways in different systems.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: How to print pointer to function?
  2019-12-18 10:05               ` David Brown
@ 2019-12-18 11:12                 ` Segher Boessenkool
  0 siblings, 0 replies; 17+ messages in thread
From: Segher Boessenkool @ 2019-12-18 11:12 UTC (permalink / raw)
  To: David Brown; +Cc: Liu Hao, gcc-help

Hi!

On Wed, Dec 18, 2019 at 11:04:07AM +0100, David Brown wrote:
> In practice, often you can write code that is portable
> to any "reasonable" implementation, and accept that the code won't work
> for other systems:
> 
> #include <limits.h>
> #if -INT_MAX == INT_MIN
> #error Only two's complement signed integers supported by this code
> #endif

(And hopefully document it, and/or even do a test like you did here).

> > 0. Conversion a value from `unsigned int` to `signed char` which doesn't
> >    fit in it yields an implementation-defined result.
> >    [C++14 now requires 2's complement, which is required by GCC.]
> 
> IIRC it is C++20 that limits the signed integer representation to two's
> complement.

Yes, that is my understanding as well.

> Note that it is entirely possible for an implementation to have two's
> complement representation but /not/ use modulo to reduce a value to fit
> into a smaller signed type.  In particular, a compiler could choose to
> raise a signal and halt with an error message (I don't know if any of
> gcc's sanitizers do that).

-fsanitize=signed-integer-overflow (part of -fsanitize=undefined, ubsan).

[ lots of good stuff snipped ]

> When you write some code, you first figure out what the code should do.
>  Then you can think about what range of systems it makes sense to
> support.  Portable coding is then usually fairly easy as long as the
> target range is sensible.

Yes, exactly.

And the only good way to avoid undefined behaviour is simply to know
what not to do.  C is not a friendly language to beginners, in that
sense.


Segher

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2019-12-18 11:12 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-12  9:30 How to print pointer to function? Josef Wolf
2019-12-12  9:44 ` Jonathan Wakely
2019-12-12  9:49 ` Liu Hao
2019-12-12 11:00   ` Josef Wolf
2019-12-17 12:56     ` Vincent Lefevre
2019-12-17 13:17       ` Liu Hao
2019-12-17 13:27         ` Segher Boessenkool
2019-12-17 14:52         ` Vincent Lefevre
2019-12-17 13:22       ` Segher Boessenkool
2019-12-17 15:23         ` Vincent Lefevre
2019-12-17 15:27         ` Manfred
2019-12-17 16:30           ` Vincent Lefevre
2019-12-17 22:49             ` Segher Boessenkool
2019-12-18  2:39             ` Liu Hao
2019-12-18 10:05               ` David Brown
2019-12-18 11:12                 ` Segher Boessenkool
2019-12-17 13:01 ` Vincent Lefevre

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).