Signedness aliasing using reinterpret_castWhat is the strict aliasing rule?What is the strict aliasing rule?When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?When to use reinterpret_cast?Generic char[] based storage and avoiding strict-aliasing related UBDo the c++11 strict alias rules allow accessing uint64_t via char *, char(&)[N],even std::array<char, N>& with -fstrict-aliasing -Wstrict-aliasing=2?Is it a strict aliasing violation to alias a struct as its first member?std::launder and strict aliasing rulereinterpret_cast vs strict aliasingStrict Aliasing Rule and Type Aliasing in C++Dealing with undefined behavior when using reinterpret_cast in a memory mapping
Teacher help me explain this to my students
Did people Unsnap to where they were?
Count Even Digits In Number
Externally monitoring CPU/SSD activity without software access
Why is a `for` loop so much faster to count True values?
Plot twist where the antagonist wins
Purpose and meaning of "dabei" in the sentence "sehen Sie dabei nicht ins Bildlexikon"?
Where have Brexit voters gone?
what kind of chord progession is this?
Count rotary dial pulses in a phone number (including letters)
Can I tell a prospective employee that everyone in the team is leaving?
How to Pin Point Large File eating space in Fedora 18
How to know if a folder is a symbolic link?
Is "cool" appropriate or offensive to use in IMs?
The usage of "run a mile" in a sentence
Is it rude to call a professor by their last name with no prefix in a non-academic setting?
I know that there is a preselected candidate for a position to be filled at my department. What should I do?
What is the object moving across the ceiling in this stock footage?
Where can I find visible/radio telescopic observations of the center of the Milky Way galaxy?
Why were helmets and other body armour not commonplace in the 1800s?
Why didn't Thanos use the Time Stone to stop the Avengers' plan?
Compaq Portable vs IBM 5155 Portable PC
Gladys goes shopping
Have 1.5% of all nuclear reactors ever built melted down?
Signedness aliasing using reinterpret_cast
What is the strict aliasing rule?What is the strict aliasing rule?When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?When to use reinterpret_cast?Generic char[] based storage and avoiding strict-aliasing related UBDo the c++11 strict alias rules allow accessing uint64_t via char *, char(&)[N],even std::array<char, N>& with -fstrict-aliasing -Wstrict-aliasing=2?Is it a strict aliasing violation to alias a struct as its first member?std::launder and strict aliasing rulereinterpret_cast vs strict aliasingStrict Aliasing Rule and Type Aliasing in C++Dealing with undefined behavior when using reinterpret_cast in a memory mapping
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
Take the following code
#include <iostream>
void func()
int i = 2147483640;
while (i < i + 1)
std::cerr << i << 'n';
++i;
return;
int main()
func();
This code is clearly wrong, as the while loop can only terminate if the signed int i overflowed, which is UB, and hence the compiler may for instance optimize this into an infinite loop (which Clang does on -O3), or do other sorts of funky things. My question now is: from my reading of the C++ standard, types that are equivalent up to signedness may alias (i.e. pointers int* and unsigned* may alias). In order to do some funky signed "wrapping", does the following have undefined behavior or not?
#include <iostream>
static int safe_inc(int a)
++reinterpret_cast<unsigned&>(a);
return a;
void func()
int i = 2147483640;
while (i < safe_inc(i))
std::cerr << i << 'n';
++i;
return;
int main()
func();
I have tried the above code with both Clang 8 and GCC 9 on -O3 with -Wall -Wextra -Wpedantic -O3 -fsanitize=address,undefined arguments and get no errors or warnings and the loop terminates after wrapping to INT_MIN.
cppreference.com tells me that
Type aliasing
Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:
- AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType.
which from my reading means that for purposes of type aliasing, signedness is not considered, and the code using reinterpret_cast has well-defined semantics (albeit being somewhat cheesy anyhow).
c++ language-lawyer undefined-behavior signed reinterpret-cast
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
|
show 11 more comments
Take the following code
#include <iostream>
void func()
int i = 2147483640;
while (i < i + 1)
std::cerr << i << 'n';
++i;
return;
int main()
func();
This code is clearly wrong, as the while loop can only terminate if the signed int i overflowed, which is UB, and hence the compiler may for instance optimize this into an infinite loop (which Clang does on -O3), or do other sorts of funky things. My question now is: from my reading of the C++ standard, types that are equivalent up to signedness may alias (i.e. pointers int* and unsigned* may alias). In order to do some funky signed "wrapping", does the following have undefined behavior or not?
#include <iostream>
static int safe_inc(int a)
++reinterpret_cast<unsigned&>(a);
return a;
void func()
int i = 2147483640;
while (i < safe_inc(i))
std::cerr << i << 'n';
++i;
return;
int main()
func();
I have tried the above code with both Clang 8 and GCC 9 on -O3 with -Wall -Wextra -Wpedantic -O3 -fsanitize=address,undefined arguments and get no errors or warnings and the loop terminates after wrapping to INT_MIN.
cppreference.com tells me that
Type aliasing
Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:
- AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType.
which from my reading means that for purposes of type aliasing, signedness is not considered, and the code using reinterpret_cast has well-defined semantics (albeit being somewhat cheesy anyhow).
c++ language-lawyer undefined-behavior signed reinterpret-cast
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Since you reinterpret the signed int as an unsigned value, the code is as correct as if you used unsigned value from the beginning (and casting thecerroutput to signed).
– xryl669
8 hours ago
3
@LightnessRacesinOrbit: [basic.lval]/11 lays down the validity of this access. What is missing is what the behavior is of modifying an unsigned/signed object through a reference to its signed/unsigned version of it. But I don't see a statement forbidding it.
– Nicol Bolas
8 hours ago
2
@SergeyA: Then point to the line in the specification that says what actually happens when you write to a signed object via a reference to an unsigned one. Because I can point to lines in the specification that says what happens when you, for example, call a member function of a derived class through a base class pointer/reference. But no such similar statements exist for signed/unsigned. The conversion is legit; the access is legit, but what happens is simply not stated by the spec.
– Nicol Bolas
7 hours ago
2
Indeed. This kind of thing has always been underspecified for my liking. It's one of the few areas of the standard that seems to assume close-to-the-metal bit logic in places
– Lightness Races in Orbit
7 hours ago
2
@SergeyA: "Could it be underspecified?" Yes, this is a defect in the spec. And with the two's complement change in C++20, it can be resolved in a completely well-defined way. There just has to be wording somewhere to do it.
– Nicol Bolas
7 hours ago
|
show 11 more comments
Take the following code
#include <iostream>
void func()
int i = 2147483640;
while (i < i + 1)
std::cerr << i << 'n';
++i;
return;
int main()
func();
This code is clearly wrong, as the while loop can only terminate if the signed int i overflowed, which is UB, and hence the compiler may for instance optimize this into an infinite loop (which Clang does on -O3), or do other sorts of funky things. My question now is: from my reading of the C++ standard, types that are equivalent up to signedness may alias (i.e. pointers int* and unsigned* may alias). In order to do some funky signed "wrapping", does the following have undefined behavior or not?
#include <iostream>
static int safe_inc(int a)
++reinterpret_cast<unsigned&>(a);
return a;
void func()
int i = 2147483640;
while (i < safe_inc(i))
std::cerr << i << 'n';
++i;
return;
int main()
func();
I have tried the above code with both Clang 8 and GCC 9 on -O3 with -Wall -Wextra -Wpedantic -O3 -fsanitize=address,undefined arguments and get no errors or warnings and the loop terminates after wrapping to INT_MIN.
cppreference.com tells me that
Type aliasing
Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:
- AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType.
which from my reading means that for purposes of type aliasing, signedness is not considered, and the code using reinterpret_cast has well-defined semantics (albeit being somewhat cheesy anyhow).
c++ language-lawyer undefined-behavior signed reinterpret-cast
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Take the following code
#include <iostream>
void func()
int i = 2147483640;
while (i < i + 1)
std::cerr << i << 'n';
++i;
return;
int main()
func();
This code is clearly wrong, as the while loop can only terminate if the signed int i overflowed, which is UB, and hence the compiler may for instance optimize this into an infinite loop (which Clang does on -O3), or do other sorts of funky things. My question now is: from my reading of the C++ standard, types that are equivalent up to signedness may alias (i.e. pointers int* and unsigned* may alias). In order to do some funky signed "wrapping", does the following have undefined behavior or not?
#include <iostream>
static int safe_inc(int a)
++reinterpret_cast<unsigned&>(a);
return a;
void func()
int i = 2147483640;
while (i < safe_inc(i))
std::cerr << i << 'n';
++i;
return;
int main()
func();
I have tried the above code with both Clang 8 and GCC 9 on -O3 with -Wall -Wextra -Wpedantic -O3 -fsanitize=address,undefined arguments and get no errors or warnings and the loop terminates after wrapping to INT_MIN.
cppreference.com tells me that
Type aliasing
Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:
- AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType.
which from my reading means that for purposes of type aliasing, signedness is not considered, and the code using reinterpret_cast has well-defined semantics (albeit being somewhat cheesy anyhow).
c++ language-lawyer undefined-behavior signed reinterpret-cast
c++ language-lawyer undefined-behavior signed reinterpret-cast
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
edited 7 hours ago
Jonas Müller
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked 8 hours ago
Jonas MüllerJonas Müller
513
513
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Jonas Müller is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Since you reinterpret the signed int as an unsigned value, the code is as correct as if you used unsigned value from the beginning (and casting thecerroutput to signed).
– xryl669
8 hours ago
3
@LightnessRacesinOrbit: [basic.lval]/11 lays down the validity of this access. What is missing is what the behavior is of modifying an unsigned/signed object through a reference to its signed/unsigned version of it. But I don't see a statement forbidding it.
– Nicol Bolas
8 hours ago
2
@SergeyA: Then point to the line in the specification that says what actually happens when you write to a signed object via a reference to an unsigned one. Because I can point to lines in the specification that says what happens when you, for example, call a member function of a derived class through a base class pointer/reference. But no such similar statements exist for signed/unsigned. The conversion is legit; the access is legit, but what happens is simply not stated by the spec.
– Nicol Bolas
7 hours ago
2
Indeed. This kind of thing has always been underspecified for my liking. It's one of the few areas of the standard that seems to assume close-to-the-metal bit logic in places
– Lightness Races in Orbit
7 hours ago
2
@SergeyA: "Could it be underspecified?" Yes, this is a defect in the spec. And with the two's complement change in C++20, it can be resolved in a completely well-defined way. There just has to be wording somewhere to do it.
– Nicol Bolas
7 hours ago
|
show 11 more comments
Since you reinterpret the signed int as an unsigned value, the code is as correct as if you used unsigned value from the beginning (and casting thecerroutput to signed).
– xryl669
8 hours ago
3
@LightnessRacesinOrbit: [basic.lval]/11 lays down the validity of this access. What is missing is what the behavior is of modifying an unsigned/signed object through a reference to its signed/unsigned version of it. But I don't see a statement forbidding it.
– Nicol Bolas
8 hours ago
2
@SergeyA: Then point to the line in the specification that says what actually happens when you write to a signed object via a reference to an unsigned one. Because I can point to lines in the specification that says what happens when you, for example, call a member function of a derived class through a base class pointer/reference. But no such similar statements exist for signed/unsigned. The conversion is legit; the access is legit, but what happens is simply not stated by the spec.
– Nicol Bolas
7 hours ago
2
Indeed. This kind of thing has always been underspecified for my liking. It's one of the few areas of the standard that seems to assume close-to-the-metal bit logic in places
– Lightness Races in Orbit
7 hours ago
2
@SergeyA: "Could it be underspecified?" Yes, this is a defect in the spec. And with the two's complement change in C++20, it can be resolved in a completely well-defined way. There just has to be wording somewhere to do it.
– Nicol Bolas
7 hours ago
Since you reinterpret the signed int as an unsigned value, the code is as correct as if you used unsigned value from the beginning (and casting the
cerr output to signed).– xryl669
8 hours ago
Since you reinterpret the signed int as an unsigned value, the code is as correct as if you used unsigned value from the beginning (and casting the
cerr output to signed).– xryl669
8 hours ago
3
3
@LightnessRacesinOrbit: [basic.lval]/11 lays down the validity of this access. What is missing is what the behavior is of modifying an unsigned/signed object through a reference to its signed/unsigned version of it. But I don't see a statement forbidding it.
– Nicol Bolas
8 hours ago
@LightnessRacesinOrbit: [basic.lval]/11 lays down the validity of this access. What is missing is what the behavior is of modifying an unsigned/signed object through a reference to its signed/unsigned version of it. But I don't see a statement forbidding it.
– Nicol Bolas
8 hours ago
2
2
@SergeyA: Then point to the line in the specification that says what actually happens when you write to a signed object via a reference to an unsigned one. Because I can point to lines in the specification that says what happens when you, for example, call a member function of a derived class through a base class pointer/reference. But no such similar statements exist for signed/unsigned. The conversion is legit; the access is legit, but what happens is simply not stated by the spec.
– Nicol Bolas
7 hours ago
@SergeyA: Then point to the line in the specification that says what actually happens when you write to a signed object via a reference to an unsigned one. Because I can point to lines in the specification that says what happens when you, for example, call a member function of a derived class through a base class pointer/reference. But no such similar statements exist for signed/unsigned. The conversion is legit; the access is legit, but what happens is simply not stated by the spec.
– Nicol Bolas
7 hours ago
2
2
Indeed. This kind of thing has always been underspecified for my liking. It's one of the few areas of the standard that seems to assume close-to-the-metal bit logic in places
– Lightness Races in Orbit
7 hours ago
Indeed. This kind of thing has always been underspecified for my liking. It's one of the few areas of the standard that seems to assume close-to-the-metal bit logic in places
– Lightness Races in Orbit
7 hours ago
2
2
@SergeyA: "Could it be underspecified?" Yes, this is a defect in the spec. And with the two's complement change in C++20, it can be resolved in a completely well-defined way. There just has to be wording somewhere to do it.
– Nicol Bolas
7 hours ago
@SergeyA: "Could it be underspecified?" Yes, this is a defect in the spec. And with the two's complement change in C++20, it can be resolved in a completely well-defined way. There just has to be wording somewhere to do it.
– Nicol Bolas
7 hours ago
|
show 11 more comments
2 Answers
2
active
oldest
votes
Aliasing here is perfectly legal. See http://eel.is/c++draft/expr.prop#basic.lval-11.2:
If a program attempts to access the stored value of an object through
a glvalue whose type is not similar ([conv.qual]) to one of the
following types the behavior is undefined:53
(11.1) the dynamic type of the object,
(11.2) a type that is the signed or unsigned type
corresponding to the dynamic type of the object
I think, it is also worth talking about the actual overflow question, which does not necessarily require reinterpret_cast. The very same effect could be achieved with implicit integral conversions
unsigned x = i;
++x;
i = x; // this would serve you just fine.
This code would be implementation defined pre-C++20, since you would be converting from the value which can't be represented by destination type.
Since C++20 this code will be well-formed.
See https://en.cppreference.com/w/cpp/language/implicit_conversion
On a side note, you might as well start with unsigned type if you want integer overflow semantic.
i wonder if one cannot do the same without thereinterpret_castviaunsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?
– formerlyknownas_463035818
8 hours ago
3
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
1
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
1
@formerlyknownas_463035818 ifaisINT_MAXthenxwould not fit back intoamaking it implementation defined behavior.
– NathanOliver
8 hours ago
1
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use ofreinterpret_castis valid here.
– Jonas Müller
8 hours ago
|
show 13 more comments
Your code is perfectly legal, cpp reference is a very good source. You can find the same information in the standard [basic.lval]/11
If a program attempts to access the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:
the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,[...]
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
2
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
|
show 1 more 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
);
);
Jonas Müller is a new contributor. Be nice, and check out our Code of Conduct.
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%2f56295309%2fsignedness-aliasing-using-reinterpret-cast%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Aliasing here is perfectly legal. See http://eel.is/c++draft/expr.prop#basic.lval-11.2:
If a program attempts to access the stored value of an object through
a glvalue whose type is not similar ([conv.qual]) to one of the
following types the behavior is undefined:53
(11.1) the dynamic type of the object,
(11.2) a type that is the signed or unsigned type
corresponding to the dynamic type of the object
I think, it is also worth talking about the actual overflow question, which does not necessarily require reinterpret_cast. The very same effect could be achieved with implicit integral conversions
unsigned x = i;
++x;
i = x; // this would serve you just fine.
This code would be implementation defined pre-C++20, since you would be converting from the value which can't be represented by destination type.
Since C++20 this code will be well-formed.
See https://en.cppreference.com/w/cpp/language/implicit_conversion
On a side note, you might as well start with unsigned type if you want integer overflow semantic.
i wonder if one cannot do the same without thereinterpret_castviaunsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?
– formerlyknownas_463035818
8 hours ago
3
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
1
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
1
@formerlyknownas_463035818 ifaisINT_MAXthenxwould not fit back intoamaking it implementation defined behavior.
– NathanOliver
8 hours ago
1
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use ofreinterpret_castis valid here.
– Jonas Müller
8 hours ago
|
show 13 more comments
Aliasing here is perfectly legal. See http://eel.is/c++draft/expr.prop#basic.lval-11.2:
If a program attempts to access the stored value of an object through
a glvalue whose type is not similar ([conv.qual]) to one of the
following types the behavior is undefined:53
(11.1) the dynamic type of the object,
(11.2) a type that is the signed or unsigned type
corresponding to the dynamic type of the object
I think, it is also worth talking about the actual overflow question, which does not necessarily require reinterpret_cast. The very same effect could be achieved with implicit integral conversions
unsigned x = i;
++x;
i = x; // this would serve you just fine.
This code would be implementation defined pre-C++20, since you would be converting from the value which can't be represented by destination type.
Since C++20 this code will be well-formed.
See https://en.cppreference.com/w/cpp/language/implicit_conversion
On a side note, you might as well start with unsigned type if you want integer overflow semantic.
i wonder if one cannot do the same without thereinterpret_castviaunsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?
– formerlyknownas_463035818
8 hours ago
3
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
1
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
1
@formerlyknownas_463035818 ifaisINT_MAXthenxwould not fit back intoamaking it implementation defined behavior.
– NathanOliver
8 hours ago
1
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use ofreinterpret_castis valid here.
– Jonas Müller
8 hours ago
|
show 13 more comments
Aliasing here is perfectly legal. See http://eel.is/c++draft/expr.prop#basic.lval-11.2:
If a program attempts to access the stored value of an object through
a glvalue whose type is not similar ([conv.qual]) to one of the
following types the behavior is undefined:53
(11.1) the dynamic type of the object,
(11.2) a type that is the signed or unsigned type
corresponding to the dynamic type of the object
I think, it is also worth talking about the actual overflow question, which does not necessarily require reinterpret_cast. The very same effect could be achieved with implicit integral conversions
unsigned x = i;
++x;
i = x; // this would serve you just fine.
This code would be implementation defined pre-C++20, since you would be converting from the value which can't be represented by destination type.
Since C++20 this code will be well-formed.
See https://en.cppreference.com/w/cpp/language/implicit_conversion
On a side note, you might as well start with unsigned type if you want integer overflow semantic.
Aliasing here is perfectly legal. See http://eel.is/c++draft/expr.prop#basic.lval-11.2:
If a program attempts to access the stored value of an object through
a glvalue whose type is not similar ([conv.qual]) to one of the
following types the behavior is undefined:53
(11.1) the dynamic type of the object,
(11.2) a type that is the signed or unsigned type
corresponding to the dynamic type of the object
I think, it is also worth talking about the actual overflow question, which does not necessarily require reinterpret_cast. The very same effect could be achieved with implicit integral conversions
unsigned x = i;
++x;
i = x; // this would serve you just fine.
This code would be implementation defined pre-C++20, since you would be converting from the value which can't be represented by destination type.
Since C++20 this code will be well-formed.
See https://en.cppreference.com/w/cpp/language/implicit_conversion
On a side note, you might as well start with unsigned type if you want integer overflow semantic.
edited 8 hours ago
answered 8 hours ago
SergeyASergeyA
46k54193
46k54193
i wonder if one cannot do the same without thereinterpret_castviaunsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?
– formerlyknownas_463035818
8 hours ago
3
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
1
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
1
@formerlyknownas_463035818 ifaisINT_MAXthenxwould not fit back intoamaking it implementation defined behavior.
– NathanOliver
8 hours ago
1
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use ofreinterpret_castis valid here.
– Jonas Müller
8 hours ago
|
show 13 more comments
i wonder if one cannot do the same without thereinterpret_castviaunsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?
– formerlyknownas_463035818
8 hours ago
3
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
1
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
1
@formerlyknownas_463035818 ifaisINT_MAXthenxwould not fit back intoamaking it implementation defined behavior.
– NathanOliver
8 hours ago
1
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use ofreinterpret_castis valid here.
– Jonas Müller
8 hours ago
i wonder if one cannot do the same without the
reinterpret_cast via unsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?– formerlyknownas_463035818
8 hours ago
i wonder if one cannot do the same without the
reinterpret_cast via unsigned x = a; ++x; return x;. Would that not have the same effect, but valid already pre c++20?– formerlyknownas_463035818
8 hours ago
3
3
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
This doesn't answer the question about aliasing though does it
– Lightness Races in Orbit
8 hours ago
1
1
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
@JonasMüller is your question about incrementing or aliasing?
– SergeyA
8 hours ago
1
1
@formerlyknownas_463035818 if
a is INT_MAX then x would not fit back into a making it implementation defined behavior.– NathanOliver
8 hours ago
@formerlyknownas_463035818 if
a is INT_MAX then x would not fit back into a making it implementation defined behavior.– NathanOliver
8 hours ago
1
1
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use of
reinterpret_cast is valid here.– Jonas Müller
8 hours ago
I agree, there's a second implicit question in here (which concerns the overflow part), but the primary question is whether the use of
reinterpret_cast is valid here.– Jonas Müller
8 hours ago
|
show 13 more comments
Your code is perfectly legal, cpp reference is a very good source. You can find the same information in the standard [basic.lval]/11
If a program attempts to access the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:
the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,[...]
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
2
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
|
show 1 more comment
Your code is perfectly legal, cpp reference is a very good source. You can find the same information in the standard [basic.lval]/11
If a program attempts to access the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:
the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,[...]
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
2
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
|
show 1 more comment
Your code is perfectly legal, cpp reference is a very good source. You can find the same information in the standard [basic.lval]/11
If a program attempts to access the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:
the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,[...]
Your code is perfectly legal, cpp reference is a very good source. You can find the same information in the standard [basic.lval]/11
If a program attempts to access the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:
the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,[...]
edited 7 hours ago
Lightness Races in Orbit
300k56486835
300k56486835
answered 8 hours ago
OlivOliv
10.5k12058
10.5k12058
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
2
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
|
show 1 more comment
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
2
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
Hmm what does "corresponding to" mean here? Certainly this is not the same wording Cubbi chose on cppreference ("variant of")
– Lightness Races in Orbit
8 hours ago
2
2
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
@LightnessRacesinOrbit eel.is/c++draft/basic.fundamental#2. Cpp reference prefers plain English, the aim is certainly to be easier to read than the standard.
– Oliv
8 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
Okay, thanks, that's concrete. :)
– Lightness Races in Orbit
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
For completeness, your code behavior is more specified according to the c++20 standard: eel.is/c++draft/basic.types#basic.fundamental-3. Nevertheless this added paragraph is just a recognition of a fact and you can safely assume your code is portable.
– Oliv
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
Well it's not my code :)
– Lightness Races in Orbit
7 hours ago
|
show 1 more comment
Jonas Müller is a new contributor. Be nice, and check out our Code of Conduct.
Jonas Müller is a new contributor. Be nice, and check out our Code of Conduct.
Jonas Müller is a new contributor. Be nice, and check out our Code of Conduct.
Jonas Müller is a new contributor. Be nice, and check out our Code of Conduct.
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%2f56295309%2fsignedness-aliasing-using-reinterpret-cast%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
Since you reinterpret the signed int as an unsigned value, the code is as correct as if you used unsigned value from the beginning (and casting the
cerroutput to signed).– xryl669
8 hours ago
3
@LightnessRacesinOrbit: [basic.lval]/11 lays down the validity of this access. What is missing is what the behavior is of modifying an unsigned/signed object through a reference to its signed/unsigned version of it. But I don't see a statement forbidding it.
– Nicol Bolas
8 hours ago
2
@SergeyA: Then point to the line in the specification that says what actually happens when you write to a signed object via a reference to an unsigned one. Because I can point to lines in the specification that says what happens when you, for example, call a member function of a derived class through a base class pointer/reference. But no such similar statements exist for signed/unsigned. The conversion is legit; the access is legit, but what happens is simply not stated by the spec.
– Nicol Bolas
7 hours ago
2
Indeed. This kind of thing has always been underspecified for my liking. It's one of the few areas of the standard that seems to assume close-to-the-metal bit logic in places
– Lightness Races in Orbit
7 hours ago
2
@SergeyA: "Could it be underspecified?" Yes, this is a defect in the spec. And with the two's complement change in C++20, it can be resolved in a completely well-defined way. There just has to be wording somewhere to do it.
– Nicol Bolas
7 hours ago