But here's the thing. Is the casting of the result of dlsym()
[to a function pointer type] necessary?
Isn't this the same as "casting the return value of malloc()", where you
But here's where it gets interesting. In the man page for dlopen(), we
find this example code and a long detailed comment:
*(void **) (&cosine) = dlsym(handle, "cos");
This (clumsy) cast conforms with the ISO C standard and will
avoid any compiler warnings.
The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a.
POSIX.1-2013) improved matters by requiring that conforming
implementations support casting 'void *' to a function pointer.
And why do we even need the "clumsy" cast? Why not just:
cosine = dlsym(handle, "cos");
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there (it imposes no requirements at all), nor that the conversion is fine with a
cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there (it
imposes no requirements at all), nor that the conversion is fine with a
cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
ISO C does require a cast. The cast is necessary to avoid a constraint violation and a mandatory diagnostic. The resulting behavior is
undefined in ISO C, but defined by POSIX.
Assigning a void* value to a pointer-to-function object without a cast violates the constraint for simple assignment (N1570 6.5.16.1p1).
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are anISO C does require a cast. The cast is necessary to avoid a
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there (it >>> imposes no requirements at all), nor that the conversion is fine with a
cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
constraint violation and a mandatory diagnostic. The resulting
behavior is undefined in ISO C, but defined by POSIX. Assigning a
void* value to a pointer-to-function object without a cast violates
the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
bart <bc@freeuk.com> writes:
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are anISO C does require a cast. The cast is necessary to avoid a
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there (it >>>> imposes no requirements at all), nor that the conversion is fine with a >>>> cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
constraint violation and a mandatory diagnostic. The resulting
behavior is undefined in ISO C, but defined by POSIX. Assigning a
void* value to a pointer-to-function object without a cast violates
the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
The warnings I get from gcc are:
warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]
With -pedantic-errors, these become fatal errors.
I disagree with gcc. ISO C doesn't define the behavior, but it doesn't forbid the conversion. (Anyone who disagrees is invited to cite the constraint that it violates.)
Note that clang doesn't issue this diagnostic.
The warnings I get from gcc are:
warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]
With -pedantic-errors, these become fatal errors.
I disagree with gcc. ISO C doesn't define the behavior, but it doesn't forbid the conversion.
Standard C does not say that any extensions are prohibited.
How silly to think so, and write about it, and code a facet of the
compiler diagnostic system that way!
I'm actually opening a GCC bugzilla about this right now.
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
Standard C does not say that any extensions are prohibited.
How silly to think so, and write about it, and code a facet of the
compiler diagnostic system that way!
I'm actually opening a GCC bugzilla about this right now.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526
On 2024-03-28, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:[...]
The warnings I get from gcc are:
warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]
With -pedantic-errors, these become fatal errors.
I disagree with gcc. ISO C doesn't define the behavior, but it doesn't
forbid the conversion.
It's never good for a diagnostic to be stating a blatant falsehood, regardless of whether the presence of the diagnostic is a good idea
or not.
I'm actually opening a GCC bugzilla about this right now.
But here's the thing. Is the casting of the result of dlsym() necessary? Isn't this the same as "casting the return value of malloc()", where you don't need to cast it since it auto-magically gets casted by being assigned to the thing on the left of the assignment?
And why do we even need the "clumsy" cast? Why not just:
cosine = dlsym(handle, "cos");
No, it isn't even remotely the same. C language allows implicit casts
from any object pointer type to `void *` and vice-versa. Which is why casting the result of `malloc` is unnecessary.
C language does not support implicit casts between object pointer
types (like `void *`) and function pointer types. Moreover, C language
still does not support _explicit_ casts between `void *` and function
pointer types either. POSIX guarantees/requirements are not C.
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there (it >>> imposes no requirements at all), nor that the conversion is fine with a
cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
ISO C does require a cast. The cast is necessary to avoid a constraint
violation and a mandatory diagnostic. The resulting behavior is
undefined in ISO C, but defined by POSIX.
Assigning a void* value to a pointer-to-function object without a cast
violates the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
bart <bc@freeuk.com> writes:
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are anISO C does require a cast. The cast is necessary to avoid a
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there (it >>>> imposes no requirements at all), nor that the conversion is fine with a >>>> cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
constraint violation and a mandatory diagnostic. The resulting
behavior is undefined in ISO C, but defined by POSIX. Assigning a
void* value to a pointer-to-function object without a cast violates
the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
The warnings I get from gcc are:
warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]
With -pedantic-errors, these become fatal errors.
I disagree with gcc. ISO C doesn't define the behavior, but it doesn't forbid the conversion. (Anyone who disagrees is invited to cite the constraint that it violates.)
Note that clang doesn't issue this diagnostic.
On 28/03/2024 21:30, bart wrote:
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast there
(it
imposes no requirements at all), nor that the conversion is fine with a >>>> cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
ISO C does require a cast. The cast is necessary to avoid a constraint
violation and a mandatory diagnostic. The resulting behavior is
undefined in ISO C, but defined by POSIX.
Assigning a void* value to a pointer-to-function object without a cast
violates the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
One method that silences all gcc warnings here is to cast via uintptr_t:
#include <stdint.h>
void* p;
void(*q)(void);
typedef void(*FVoid)(void);
void foo(void) {
p = (void*) (uintptr_t) q;
}
void bar(void) {
q = (FVoid) (uintptr_t) p;
}
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
Standard C does not say that any extensions are prohibited.
How silly to think so, and write about it, and code a facet of the
compiler diagnostic system that way!
I'm actually opening a GCC bugzilla about this right now.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526
Hilarious pushback ensues.
On Thu, 28 Mar 2024 22:33:56 -0000 (UTC)
Kaz Kylheku <433-929-6894@kylheku.com> wrote:
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
Standard C does not say that any extensions are prohibited.
How silly to think so, and write about it, and code a facet of
the compiler diagnostic system that way!
I'm actually opening a GCC bugzilla about this right now.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526
Hilarious pushback ensues.
You got one commentator on your side.
On Fri, 29 Mar 2024 15:53:10 +0200
Michael S <already5chosen@yahoo.com> wrote:
On Thu, 28 Mar 2024 22:33:56 -0000 (UTC)
Kaz Kylheku <433-929-6894@kylheku.com> wrote:
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
On 2024-03-28, Kaz Kylheku <433-929-6894@kylheku.com> wrote:
Standard C does not say that any extensions are prohibited.
How silly to think so, and write about it, and code a facet of
the compiler diagnostic system that way!
I'm actually opening a GCC bugzilla about this right now.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526
Hilarious pushback ensues.
You got one commentator on your side.
BTW, I tried to find out who are Harald van Dijk and Joseph S. Myers
(the post of the later sounds like one of insider) but failed.
Did gcc Bugzilla silently disabled "Search By People" option?
Or I am holding it wrong?
On 29/03/2024 12:58, David Brown wrote:
On 28/03/2024 21:30, bart wrote:
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast
there (it
imposes no requirements at all), nor that the conversion is fine
with a
cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
ISO C does require a cast. The cast is necessary to avoid a constraint >>>> violation and a mandatory diagnostic. The resulting behavior is
undefined in ISO C, but defined by POSIX.
Assigning a void* value to a pointer-to-function object without a cast >>>> violates the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
One method that silences all gcc warnings here is to cast via uintptr_t:
#include <stdint.h>
void* p;
void(*q)(void);
typedef void(*FVoid)(void);
void foo(void) {
p = (void*) (uintptr_t) q;
}
void bar(void) {
q = (FVoid) (uintptr_t) p;
}
I was aware of the double conversion but KT used 'a cast' so I wondered
if there was a single cast that could be used.
It is odd however that function and object pointers can be considered so different that even an explicit conversion between them is deemed to be meaningless.
Yet converting either to and from an integer type is perfectly fine,
even though it isn't even a pointer type!
I wonder then why a conversion between function and object couldn't be implemented, internally, via such an intermediate integer type anyway.
On 28/03/2024 22:07, Keith Thompson wrote:
bart <bc@freeuk.com> writes:
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are anISO C does require a cast. The cast is necessary to avoid a
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast
there (it
imposes no requirements at all), nor that the conversion is fine
with a
cast.
The cast is /likely/ necessary, in order to correctly trigger the
extension.
constraint violation and a mandatory diagnostic. The resulting
behavior is undefined in ISO C, but defined by POSIX. Assigning a
void* value to a pointer-to-function object without a cast violates
the constraint for simple assignment (N1570 6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
The warnings I get from gcc are:
warning: ISO C forbids conversion of function pointer to object
pointer type [-Wpedantic]
warning: ISO C forbids conversion of object pointer to function
pointer type [-Wpedantic]
With -pedantic-errors, these become fatal errors.
I disagree with gcc. ISO C doesn't define the behavior, but it doesn't
forbid the conversion. (Anyone who disagrees is invited to cite the
constraint that it violates.)
I think that the C standards don't forbid the conversion, but the description of pointer conversions (6.3.2.3) does not describe such conversions. That makes it, AFAICS, undefined behaviour rather than "forbidden" (which I would define as something that mandates a diagnostic).
Dereferencing such converted pointers might be undefined behaviour (if
you haven't converted back to the original type), or implementation-dependent behaviour (if the conversions change the
bitwise representation of the pointer).
I personally think it's good that gcc has this diagnostic, even if the message text is not strictly accurate.
Note that clang doesn't issue this diagnostic.
I think this is a variation on that old CLC standard "Why you should not
cast the return value of malloc()".
Caution: POSIX (non-strict ISO) stuff coming up. If this bothers you, please hit "next" right now.
I frequently write "interposer" functions as shared libraries (on Linux). Generally, this requires using dlsym() and RTLD_NEXT to get a pointer to the "real" function, so that you can call that as part of your interposer routine. I have always done it like this (e.g., for a function returning char *, taking 2 size_t args - just to pick an arbitrary example to make things more concrete):
char *someFunction(size_t,size_t) {
static char * (*real_someFunction) (size_t,size_t);
if (!real_someFunction)
real_someFunction =
(char * (*real_someFunction) (size_t,size_t))
dlsym(RTLD_NEXT,"someFunction");
...
}
This works fine (and compiles clean with the usual -W -Wall -Werror).
But here's the thing. Is the casting of the result of dlsym() necessary? Isn't this the same as "casting the return value of malloc()", where you don't need to cast it since it auto-magically gets casted by being assigned to the thing on the left of the assignment?
Note that it is duplicative, having to specify the type info for the
function pointer twice - once in the declaration of the pointer and
then again in the dlsym() call. It'd be better (in terms of
maintenance) if you only had to do it once.
But here's where it gets interesting. In the man page for dlopen(), we
find this example code and a long detailed comment:
double (*cosine)(double);
...
cosine = (double (*)(double)) dlsym(handle, "cos");
/* According to the ISO C standard, casting between function
pointers and 'void *', as done above, produces undefined results.
POSIX.1-2003 and POSIX.1-2008 accepted this state of affairs and
proposed the following workaround:
*(void **) (&cosine) = dlsym(handle, "cos");
This (clumsy) cast conforms with the ISO C standard and will
avoid any compiler warnings.
The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a.
POSIX.1-2013) improved matters by requiring that conforming
implementations support casting 'void *' to a function pointer.
Nevertheless, some compilers (e.g., gcc with the '-pedantic'
option) may complain about the cast used in this program. */
So, they seem to think the cast is necessary - or at least a good idea,
Are they right?
And why do we even need the "clumsy" cast? Why not just:
cosine = dlsym(handle, "cos");
On 29/03/2024 12:58, David Brown wrote:
On 28/03/2024 21:30, bart wrote:
On 28/03/2024 19:38, Keith Thompson wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
[...]
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
Therefore we can neither say that ISO C doesn't require a cast
there (it imposes no requirements at all), nor that the
conversion is fine with a cast.
The cast is /likely/ necessary, in order to correctly trigger
the extension.
ISO C does require a cast. The cast is necessary to avoid a
constraint violation and a mandatory diagnostic. The resulting
behavior is undefined in ISO C, but defined by POSIX.
Assigning a void* value to a pointer-to-function object without a
cast violates the constraint for simple assignment (N1570
6.5.16.1p1).
What would such a cast look like? Since this gives a warning with
-Wpedantic even with a cast:
void* p;
void(*q)(void);
p=(void*)q;
q=(void(*)(void))p;
One method that silences all gcc warnings here is to cast via
uintptr_t:
#include <stdint.h>
void* p;
void(*q)(void);
typedef void(*FVoid)(void);
void foo(void) {
p = (void*) (uintptr_t) q;
}
void bar(void) {
q = (FVoid) (uintptr_t) p;
}
I was aware of the double conversion but KT used 'a cast' so I
wondered if there was a single cast that could be used.
It is odd however that function and object pointers can be
considered so different that even an explicit conversion
between them is deemed to be meaningless.
Yet converting either to and from an integer type is perfectly
fine, even though it isn't even a pointer type!
I wonder then why a conversion between function and object
couldn't be implemented, internally, via such an intermediate
integer type anyway.
bart <bc@freeuk.com> writes:
I was aware of the double conversion but KT used 'a cast' so I
wondered if there was a single cast that could be used.
There is not, if it's important that it work reliably across
different compilers and different platforms.
It is odd however that function and object pointers can be
considered so different that even an explicit conversion
between them is deemed to be meaningless.
Function pointers and object pointers don't have to be the same
size, or use the same form of representation. The C standard
allows implementations where code and data live in completely
separate memories. In such cases there is no sensible way to
convert between the two kinds of pointers, because the two kinds
of addresses have no relationship to each other.
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2024-03-28, Kenny McCormack <gazelle@shell.xmission.com> wrote:
But here's the thing. Is the casting of the result of dlsym()
[to a function pointer type] necessary?
Isn't this the same as "casting the return value of malloc()", where you
Conversions between function pointers and data pointers are an
extension; it is not well-defined behavior in ISO C.
I also seem to remember something like this, but I cannot trust this
documentation without a chapter-and-verse citation.
https://pubs.opengroup.org/onlinepubs/9699919799/functions/dlsym.html
Assuming it is true, there you have it; if you're on POSIX, the compiler
is required to have the extension and it is connected to casting,
in which case the cast is required.
I've used this form for the last two decades, with gcc, with no
issues:
/**
* Each shared object that simulates a Data Link Processor (DLP), will
* contain a single namespace-scope function <b>get_dlp</b> which constructs
* a DLP object of the specified type (for example, a #c_uniline_dlp,
* #c_card_reader_dlp, et alia). <b>get_dlp</b> returns the constructed
* object as a #c_dlp object to the #channel function, which is then used
* by the I/O subsystem to request services of the DLP at the MLI level.
*/
typedef c_dlp* (*get_dlp_t)(const char *, uint64_t, c_logger *);
...
get_dlp_t sym;
...
sym = (get_dlp_t)dlsym(handle, "get_dlp");
if (sym == NULL) {
lp->log("Invalid DLP shared object format: %s\n", dlerror());
unregister_handle(channel);
dlclose(handle);
return 1;
}
I think there was a time in the development of GCC when there was
a warning even with the cast. I don't think it's enabled by default
now?
We compile with -Wall -Werror and have never seen any warnings related to casting the result of dlsym(), and we build with GCC[4..13].
scott@slp53.sl.home (Scott Lurndal) writes:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2024-03-28, Kenny McCormack <gazelle@shell.xmission.com> wrote:
* Each shared object that simulates a Data Link Processor (DLP), will
* contain a single namespace-scope function <b>get_dlp</b> which constructs >> * a DLP object of the specified type (for example, a #c_uniline_dlp,
* #c_card_reader_dlp, et alia). <b>get_dlp</b> returns the constructed
* object as a #c_dlp object to the #channel function, which is then used
* by the I/O subsystem to request services of the DLP at the MLI level.
*/
typedef c_dlp* (*get_dlp_t)(const char *, uint64_t, c_logger *);
...
get_dlp_t sym;
...
sym = (get_dlp_t)dlsym(handle, "get_dlp");
if (sym == NULL) {
lp->log("Invalid DLP shared object format: %s\n", dlerror());
unregister_handle(channel);
dlclose(handle);
return 1;
}
I think there was a time in the development of GCC when there was
a warning even with the cast. I don't think it's enabled by default
now?
We compile with -Wall -Werror and have never seen any warnings related to
casting the result of dlsym(), and we build with GCC[4..13].
Do you use -pedantic? Compiling with -pedantic using gcc 8.4.0
gives a warning diagnostic (and a fatal error if -pedantic-errors
is specified in place of -pedantic).
We write production code not standard C (or in this
case, C++) code. Portability to compilers other than gcc is
not a requirement for the several million line codebase.
On Sat, 30 Mar 2024 19:29:50 GMT, Scott Lurndal wrote:
We write production code not standard C (or in this
case, C++) code. Portability to compilers other than gcc is
not a requirement for the several million line codebase.
Interesting. Has GCC become the de-facto-standard C compiler?
On Sat, 30 Mar 2024 19:29:50 GMT, Scott Lurndal wrote:
We write production code not standard C (or in this
case, C++) code. Portability to compilers other than gcc is
not a requirement for the several million line codebase.
Interesting. Has GCC become the de-facto-standard C compiler?
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
scott@slp53.sl.home (Scott Lurndal) writes:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2024-03-28, Kenny McCormack <gazelle@shell.xmission.com> wrote:
* Each shared object that simulates a Data Link Processor (DLP),
* will contain a single namespace-scope function <b>get_dlp</b>
* which constructs a DLP object of the specified type (for example,
* a #c_uniline_dlp, #c_card_reader_dlp, et alia). <b>get_dlp</b>
* returns the constructed object as a #c_dlp object to the #channel
* function, which is then used by the I/O subsystem to request
* services of the DLP at the MLI level.
*/
typedef c_dlp* (*get_dlp_t)(const char *, uint64_t, c_logger *);
...
get_dlp_t sym;
...
sym = (get_dlp_t)dlsym(handle, "get_dlp");
if (sym == NULL) {
lp->log("Invalid DLP shared object format: %s\n", dlerror());
unregister_handle(channel);
dlclose(handle);
return 1;
}
I think there was a time in the development of GCC when there was
a warning even with the cast. I don't think it's enabled by default
now?
We compile with -Wall -Werror and have never seen any warnings related
to casting the result of dlsym(), and we build with GCC[4..13].
Do you use -pedantic? Compiling with -pedantic using gcc 8.4.0
gives a warning diagnostic (and a fatal error if -pedantic-errors
is specified in place of -pedantic).
Of course not. We write production code not standard C (or in this
case, C++) code. Portability to compilers other than gcc is
not a requirement for the several million line codebase.
On 30/03/2024 09:32, Tim Rentsch wrote:
bart <bc@freeuk.com> writes:
I was aware of the double conversion but KT used 'a cast' so I
wondered if there was a single cast that could be used.
There is not, if it's important that it work reliably across
different compilers and different platforms.
It is odd however that function and object pointers can be
considered so different that even an explicit conversion
between them is deemed to be meaningless.
Function pointers and object pointers don't have to be the same
size, or use the same form of representation. The C standard
allows implementations where code and data live in completely
separate memories. In such cases there is no sensible way to
convert between the two kinds of pointers, because the two kinds
of addresses have no relationship to each other.
Suppose a object pointer is 32 bits, and a function pointer is a
32-byte descriptor.
An implementation could choose to present a function pointer as a
32-bit object pointer, which points to the full 32-byte descriptor in
data memory.
The simplest way of doing that is to have, for each function (or each
one whose address is taken), a fixed corresponding descriptor in data
memory. So here function and object pointers can be exactly the same
size, and can both refer to data memory, as far as the programmer is concerned.
Dereferencing such a function pointer, to call the function, will
involve an extra bit of indirection. It would need something extra
anyway to deal with those 32 bytes.
scott@slp53.sl.home (Scott Lurndal) writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
scott@slp53.sl.home (Scott Lurndal) writes:
We compile with -Wall -Werror and have never seen any warnings related >>>> to casting the result of dlsym(), and we build with GCC[4..13].
Do you use -pedantic? Compiling with -pedantic using gcc 8.4.0
gives a warning diagnostic (and a fatal error if -pedantic-errors
is specified in place of -pedantic).
Of course not. We write production code not standard C (or in this
case, C++) code. Portability to compilers other than gcc is
not a requirement for the several million line codebase.
It's quite amusing to hear of a team that insists on -Wall but
avoids -pedantic, saving a tiny drizzle of cases (all of which
are easy to remedy) while enduring the ever-changing force 5
blizzard of conditions tested by -Wall.
Sysop: | Tetrazocine |
---|---|
Location: | Melbourne, VIC, Australia |
Users: | 7 |
Nodes: | 8 (0 / 8) |
Uptime: | 121:19:58 |
Calls: | 46 |
Files: | 21,492 |
Messages: | 64,803 |