Why do compilers behave differently when static_cast(ing) a function to void*?
The following code compiles without any error in VSC++2017 and doesn't compile in gcc 7.3.0 (error: invalid static_cast from type ‘int(int)’ to type ‘void*’
)
void* p = static_cast<void*>(func)
#include <iostream>
int func(int x) { return 2 * x; }
int main() {
void* p = static_cast<void*>(func);
return 0;
}
c++ function-pointers void-pointers static-cast
add a comment |
The following code compiles without any error in VSC++2017 and doesn't compile in gcc 7.3.0 (error: invalid static_cast from type ‘int(int)’ to type ‘void*’
)
void* p = static_cast<void*>(func)
#include <iostream>
int func(int x) { return 2 * x; }
int main() {
void* p = static_cast<void*>(func);
return 0;
}
c++ function-pointers void-pointers static-cast
1
Function pointers are a bit weird. I'd have to go Standard diving, but I'm pretty sure MSVC is bending the Standard for their own nefarious purposes.
– user4581301
5 hours ago
2
@user4581301 Not really – the other question is about C, and there might be differences in the languages...
– Aconcagua
4 hours ago
1
While function pointers are different animals than object pointers, most incompatibilities occur when thesizeof()
the two differ. If they are the same you can usually safely convert back and forth to avoid*
. Even so, while it may work, it's not portable and just one of those things best avoided.
– doug
4 hours ago
add a comment |
The following code compiles without any error in VSC++2017 and doesn't compile in gcc 7.3.0 (error: invalid static_cast from type ‘int(int)’ to type ‘void*’
)
void* p = static_cast<void*>(func)
#include <iostream>
int func(int x) { return 2 * x; }
int main() {
void* p = static_cast<void*>(func);
return 0;
}
c++ function-pointers void-pointers static-cast
The following code compiles without any error in VSC++2017 and doesn't compile in gcc 7.3.0 (error: invalid static_cast from type ‘int(int)’ to type ‘void*’
)
void* p = static_cast<void*>(func)
#include <iostream>
int func(int x) { return 2 * x; }
int main() {
void* p = static_cast<void*>(func);
return 0;
}
c++ function-pointers void-pointers static-cast
c++ function-pointers void-pointers static-cast
edited 5 hours ago
Fabio Turati
2,63452341
2,63452341
asked 5 hours ago
Soulimane MammarSoulimane Mammar
521413
521413
1
Function pointers are a bit weird. I'd have to go Standard diving, but I'm pretty sure MSVC is bending the Standard for their own nefarious purposes.
– user4581301
5 hours ago
2
@user4581301 Not really – the other question is about C, and there might be differences in the languages...
– Aconcagua
4 hours ago
1
While function pointers are different animals than object pointers, most incompatibilities occur when thesizeof()
the two differ. If they are the same you can usually safely convert back and forth to avoid*
. Even so, while it may work, it's not portable and just one of those things best avoided.
– doug
4 hours ago
add a comment |
1
Function pointers are a bit weird. I'd have to go Standard diving, but I'm pretty sure MSVC is bending the Standard for their own nefarious purposes.
– user4581301
5 hours ago
2
@user4581301 Not really – the other question is about C, and there might be differences in the languages...
– Aconcagua
4 hours ago
1
While function pointers are different animals than object pointers, most incompatibilities occur when thesizeof()
the two differ. If they are the same you can usually safely convert back and forth to avoid*
. Even so, while it may work, it's not portable and just one of those things best avoided.
– doug
4 hours ago
1
1
Function pointers are a bit weird. I'd have to go Standard diving, but I'm pretty sure MSVC is bending the Standard for their own nefarious purposes.
– user4581301
5 hours ago
Function pointers are a bit weird. I'd have to go Standard diving, but I'm pretty sure MSVC is bending the Standard for their own nefarious purposes.
– user4581301
5 hours ago
2
2
@user4581301 Not really – the other question is about C, and there might be differences in the languages...
– Aconcagua
4 hours ago
@user4581301 Not really – the other question is about C, and there might be differences in the languages...
– Aconcagua
4 hours ago
1
1
While function pointers are different animals than object pointers, most incompatibilities occur when the
sizeof()
the two differ. If they are the same you can usually safely convert back and forth to a void*
. Even so, while it may work, it's not portable and just one of those things best avoided.– doug
4 hours ago
While function pointers are different animals than object pointers, most incompatibilities occur when the
sizeof()
the two differ. If they are the same you can usually safely convert back and forth to a void*
. Even so, while it may work, it's not portable and just one of those things best avoided.– doug
4 hours ago
add a comment |
1 Answer
1
active
oldest
votes
Functions are implicitly convertible only to function pointers. A function pointer is not a pointer in the strict meaning of the word in the language, which refers only to pointers to objects.
Function pointers cannot be converted to void*
using static_cast
. The shown program is ill-formed. If a compiler does not warn, then it fails to conform to the standard. Failing to compile an ill-formed program does not violate the standard.
On systems where void*
is guaranteed to be able to point to a function (such as POSIX), you can use reinterpret_cast
instead:
void* p = reinterpret_cast<void*>(func);
But this is not portable to systems that lack the guarantee. (I know of no system that has a C++ compiler and does not have this guarantee, but that does not mean such system does not exist).
Standard quote:
[expr.reinterpret.cast]
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in both
directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification,
shall yield the original pointer value.
Note that this conditional support does not extend to pointers to member functions. Pointers to member functions are not function pointers.
1
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to makedlsym
work.
– Ben Voigt
4 hours ago
@BenVoigt - that's true, but it won't be done withstatic_cast
. It can be done withreinterpret_cast
or a C-style cast.
– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55319602%2fwhy-do-compilers-behave-differently-when-static-casting-a-function-to-void%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Functions are implicitly convertible only to function pointers. A function pointer is not a pointer in the strict meaning of the word in the language, which refers only to pointers to objects.
Function pointers cannot be converted to void*
using static_cast
. The shown program is ill-formed. If a compiler does not warn, then it fails to conform to the standard. Failing to compile an ill-formed program does not violate the standard.
On systems where void*
is guaranteed to be able to point to a function (such as POSIX), you can use reinterpret_cast
instead:
void* p = reinterpret_cast<void*>(func);
But this is not portable to systems that lack the guarantee. (I know of no system that has a C++ compiler and does not have this guarantee, but that does not mean such system does not exist).
Standard quote:
[expr.reinterpret.cast]
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in both
directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification,
shall yield the original pointer value.
Note that this conditional support does not extend to pointers to member functions. Pointers to member functions are not function pointers.
1
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to makedlsym
work.
– Ben Voigt
4 hours ago
@BenVoigt - that's true, but it won't be done withstatic_cast
. It can be done withreinterpret_cast
or a C-style cast.
– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
add a comment |
Functions are implicitly convertible only to function pointers. A function pointer is not a pointer in the strict meaning of the word in the language, which refers only to pointers to objects.
Function pointers cannot be converted to void*
using static_cast
. The shown program is ill-formed. If a compiler does not warn, then it fails to conform to the standard. Failing to compile an ill-formed program does not violate the standard.
On systems where void*
is guaranteed to be able to point to a function (such as POSIX), you can use reinterpret_cast
instead:
void* p = reinterpret_cast<void*>(func);
But this is not portable to systems that lack the guarantee. (I know of no system that has a C++ compiler and does not have this guarantee, but that does not mean such system does not exist).
Standard quote:
[expr.reinterpret.cast]
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in both
directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification,
shall yield the original pointer value.
Note that this conditional support does not extend to pointers to member functions. Pointers to member functions are not function pointers.
1
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to makedlsym
work.
– Ben Voigt
4 hours ago
@BenVoigt - that's true, but it won't be done withstatic_cast
. It can be done withreinterpret_cast
or a C-style cast.
– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
add a comment |
Functions are implicitly convertible only to function pointers. A function pointer is not a pointer in the strict meaning of the word in the language, which refers only to pointers to objects.
Function pointers cannot be converted to void*
using static_cast
. The shown program is ill-formed. If a compiler does not warn, then it fails to conform to the standard. Failing to compile an ill-formed program does not violate the standard.
On systems where void*
is guaranteed to be able to point to a function (such as POSIX), you can use reinterpret_cast
instead:
void* p = reinterpret_cast<void*>(func);
But this is not portable to systems that lack the guarantee. (I know of no system that has a C++ compiler and does not have this guarantee, but that does not mean such system does not exist).
Standard quote:
[expr.reinterpret.cast]
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in both
directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification,
shall yield the original pointer value.
Note that this conditional support does not extend to pointers to member functions. Pointers to member functions are not function pointers.
Functions are implicitly convertible only to function pointers. A function pointer is not a pointer in the strict meaning of the word in the language, which refers only to pointers to objects.
Function pointers cannot be converted to void*
using static_cast
. The shown program is ill-formed. If a compiler does not warn, then it fails to conform to the standard. Failing to compile an ill-formed program does not violate the standard.
On systems where void*
is guaranteed to be able to point to a function (such as POSIX), you can use reinterpret_cast
instead:
void* p = reinterpret_cast<void*>(func);
But this is not portable to systems that lack the guarantee. (I know of no system that has a C++ compiler and does not have this guarantee, but that does not mean such system does not exist).
Standard quote:
[expr.reinterpret.cast]
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in both
directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification,
shall yield the original pointer value.
Note that this conditional support does not extend to pointers to member functions. Pointers to member functions are not function pointers.
edited 2 hours ago
answered 4 hours ago
eerorikaeerorika
87.2k663134
87.2k663134
1
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to makedlsym
work.
– Ben Voigt
4 hours ago
@BenVoigt - that's true, but it won't be done withstatic_cast
. It can be done withreinterpret_cast
or a C-style cast.
– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
add a comment |
1
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to makedlsym
work.
– Ben Voigt
4 hours ago
@BenVoigt - that's true, but it won't be done withstatic_cast
. It can be done withreinterpret_cast
or a C-style cast.
– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
1
1
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to make
dlsym
work.– Ben Voigt
4 hours ago
POSIX requires interconvertibility between function pointers (code addresses) and object pointers (data addresses), it's necessary to make
dlsym
work.– Ben Voigt
4 hours ago
@BenVoigt - that's true, but it won't be done with
static_cast
. It can be done with reinterpret_cast
or a C-style cast.– Peter
3 hours ago
@BenVoigt - that's true, but it won't be done with
static_cast
. It can be done with reinterpret_cast
or a C-style cast.– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
On this answer - the standard says nothing about "warnings". The standard requires diagnostics if a program is ill-formed and the error message in the question represents a diagnostic. But the standard neither requires nor forbids warnings (messages about suspicious constructs, etc, that do not prevent code from compiling) - they are discretionary features offered by implementations (and often an indicator of "quality of implementation"). Their absence does not indicate non-compliance with the standard.
– Peter
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@Peter the standard requires a diagnostic if the program is ill-formed (unless specified otherwise). The shown program is ill-formed. A diagnostic is required. A warning is a form of a diagnostic, and issuing a warning would be sufficient to conform to the standard. Lack of a diagnostic is violation of the standard.
– eerorika
3 hours ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
@eerorika - You're conflating terms. The term "diagnostic" has a specific definition in the standard as being required by the standard in specified circumstances. Warnings generally provide additional information, not mandated by the standard, because vendors choose to do so, as an aid for developers (usually because the compiler does more analysis than the standard requires, so can provide additional information). To YOU a warning may be a diagnostic. To the C++ standards, by definition in the standards, it is not.
– Peter
18 mins ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55319602%2fwhy-do-compilers-behave-differently-when-static-casting-a-function-to-void%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Function pointers are a bit weird. I'd have to go Standard diving, but I'm pretty sure MSVC is bending the Standard for their own nefarious purposes.
– user4581301
5 hours ago
2
@user4581301 Not really – the other question is about C, and there might be differences in the languages...
– Aconcagua
4 hours ago
1
While function pointers are different animals than object pointers, most incompatibilities occur when the
sizeof()
the two differ. If they are the same you can usually safely convert back and forth to avoid*
. Even so, while it may work, it's not portable and just one of those things best avoided.– doug
4 hours ago