Why do implementations of “stdint.h” disagree on the definition of UINT8_C?Why does the most negative int...
4-dimensional Knight's Tour
How can I make Ubuntu run well (including with wifi) on a 32-bit machine?
Decode a variable-length quantity
Does the United States guarantee any unique freedoms?
Was there ever a difference between 'volo' and 'volo'?
Secure my password from unsafe servers
Can ads on a page read my password?
Short story about a teenager who has his brain replaced with a microchip (Psychological Horror)
How does The Fools Guild make its money?
Are any British or English Acts of Parliament still in force in the United States?
Is it allowed and safe to carry a passenger / non-pilot in the front seat of a small general aviation airplane?
Why are the inside diameters of some pipe larger than the stated size?
How to avoid ci-driven development..?
Why is there a need to prevent a racist, sexist, or otherwise bigoted vendor from discriminating who they sell to?
Half-rock- half-forest-gnome
Do other countries guarantee freedoms that the United States does not have?
How would I as a DM create a smart phone-like spell/device my players could use?
Look mom! I made my own (Base 10) numeral system!
Validation and verification of mathematical models
sytemctl status log output
Is alignment needed after replacing upper control arms?
How is the return type of a ternary operator determined?
Does this smartphone photo show Mars just below the Sun?
In Pokémon Go, why does one of my Pikachu have an option to evolve, but another one doesn't?
Why do implementations of “stdint.h” disagree on the definition of UINT8_C?
Why does the most negative int value cause an error about ambiguous function overloads?With arrays, why is it the case that a[5] == 5[a]?The Definitive C++ Book Guide and ListWhy can templates only be implemented in the header file?What is the difference between a definition and a declaration?Why is “using namespace std;” considered bad practice?Why are elementwise additions much faster in separate loops than in a combined loop?Why is reading lines from stdin much slower in C++ than Python?Why is processing a sorted array faster than processing an unsorted array?Why Microsoft Visual Studio cannot find <stdint.h>?Why should I use a pointer rather than the object itself?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
The UINT8_C macro is defined in "stdint.h", with the following specification: The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.
In the wild, however, implementations differ:
#define UINT8_C(value) ((uint8_t) __CONCAT(value, U)) // AVR-libc
#define UINT8_C(x_) (static_cast<std::uint8_t>(x_)) // QP/C++
#define UINT8_C(c) c // GNU C Library
The first two implementations seem roughly equivalent, but the third one behaves differently: for example, the following program prints 1 with AVR-libc and QP/C++, but -1 with glibc (because right shifts on signed values propagate the sign bit).
std::cout << (UINT8_C(-1) >> 7) << std::endl; // prints -1 in glibc
The implementation of UINT16_C displays the same behavior, but not UINT32_C, because its definition includes the U suffix:
#define UINT32_C(c) c ## U
Interestingly, glibc's definition of UINT8_C changed in 2006, due to a bug report. The previous definition was #define UINT8_C(c) c ## U, but that produced incorrect output (false) on -1 < UINT8_C(0) due to integer promotion rules.
Are all three definitions correct according to the standard? Are there other differences (besides the handling of negative constants) between these three implementations?
c++ c standards integer-promotion stdint
|
show 6 more comments
The UINT8_C macro is defined in "stdint.h", with the following specification: The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.
In the wild, however, implementations differ:
#define UINT8_C(value) ((uint8_t) __CONCAT(value, U)) // AVR-libc
#define UINT8_C(x_) (static_cast<std::uint8_t>(x_)) // QP/C++
#define UINT8_C(c) c // GNU C Library
The first two implementations seem roughly equivalent, but the third one behaves differently: for example, the following program prints 1 with AVR-libc and QP/C++, but -1 with glibc (because right shifts on signed values propagate the sign bit).
std::cout << (UINT8_C(-1) >> 7) << std::endl; // prints -1 in glibc
The implementation of UINT16_C displays the same behavior, but not UINT32_C, because its definition includes the U suffix:
#define UINT32_C(c) c ## U
Interestingly, glibc's definition of UINT8_C changed in 2006, due to a bug report. The previous definition was #define UINT8_C(c) c ## U, but that produced incorrect output (false) on -1 < UINT8_C(0) due to integer promotion rules.
Are all three definitions correct according to the standard? Are there other differences (besides the handling of negative constants) between these three implementations?
c++ c standards integer-promotion stdint
5
In C++ you want to#include <cstdint>, notstdint.h- just saying.
– Jesper Juhl
8 hours ago
2
Implementations can't be controlled by the standard; the implementation can do what it likes, but is supposed to be guided by the standard. Implementations actually do their own thing. It is not hard to argue that the GNU C Library version isn't very accurate, but in a C (as opposed to C++) library, it is hard to know when it will make a difference (since almost any use of the macro will be expanded tointbefore anything further happens).
– Jonathan Leffler
8 hours ago
1
@chris That's the point: Casting -1 to an unsigned type should theoretically yield the maximum representable value of that type (and subsequently behave just fine when right-shifted).
– Max Langhof
8 hours ago
2
Since requirement is "expand to an integer constant expression corresponding to the type uint_leastN_t", I'd expect a cast of whatever is within as in((uint_least8_t) (c))
– chux
8 hours ago
1
@MaxLanghof, My bad, I glossed over the sign mismatch of the value andUINT8_C.
– chris
8 hours ago
|
show 6 more comments
The UINT8_C macro is defined in "stdint.h", with the following specification: The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.
In the wild, however, implementations differ:
#define UINT8_C(value) ((uint8_t) __CONCAT(value, U)) // AVR-libc
#define UINT8_C(x_) (static_cast<std::uint8_t>(x_)) // QP/C++
#define UINT8_C(c) c // GNU C Library
The first two implementations seem roughly equivalent, but the third one behaves differently: for example, the following program prints 1 with AVR-libc and QP/C++, but -1 with glibc (because right shifts on signed values propagate the sign bit).
std::cout << (UINT8_C(-1) >> 7) << std::endl; // prints -1 in glibc
The implementation of UINT16_C displays the same behavior, but not UINT32_C, because its definition includes the U suffix:
#define UINT32_C(c) c ## U
Interestingly, glibc's definition of UINT8_C changed in 2006, due to a bug report. The previous definition was #define UINT8_C(c) c ## U, but that produced incorrect output (false) on -1 < UINT8_C(0) due to integer promotion rules.
Are all three definitions correct according to the standard? Are there other differences (besides the handling of negative constants) between these three implementations?
c++ c standards integer-promotion stdint
The UINT8_C macro is defined in "stdint.h", with the following specification: The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.
In the wild, however, implementations differ:
#define UINT8_C(value) ((uint8_t) __CONCAT(value, U)) // AVR-libc
#define UINT8_C(x_) (static_cast<std::uint8_t>(x_)) // QP/C++
#define UINT8_C(c) c // GNU C Library
The first two implementations seem roughly equivalent, but the third one behaves differently: for example, the following program prints 1 with AVR-libc and QP/C++, but -1 with glibc (because right shifts on signed values propagate the sign bit).
std::cout << (UINT8_C(-1) >> 7) << std::endl; // prints -1 in glibc
The implementation of UINT16_C displays the same behavior, but not UINT32_C, because its definition includes the U suffix:
#define UINT32_C(c) c ## U
Interestingly, glibc's definition of UINT8_C changed in 2006, due to a bug report. The previous definition was #define UINT8_C(c) c ## U, but that produced incorrect output (false) on -1 < UINT8_C(0) due to integer promotion rules.
Are all three definitions correct according to the standard? Are there other differences (besides the handling of negative constants) between these three implementations?
c++ c standards integer-promotion stdint
c++ c standards integer-promotion stdint
edited 8 hours ago
πάντα ῥεῖ
76k10 gold badges81 silver badges149 bronze badges
76k10 gold badges81 silver badges149 bronze badges
asked 8 hours ago
ClémentClément
6,56312 gold badges51 silver badges90 bronze badges
6,56312 gold badges51 silver badges90 bronze badges
5
In C++ you want to#include <cstdint>, notstdint.h- just saying.
– Jesper Juhl
8 hours ago
2
Implementations can't be controlled by the standard; the implementation can do what it likes, but is supposed to be guided by the standard. Implementations actually do their own thing. It is not hard to argue that the GNU C Library version isn't very accurate, but in a C (as opposed to C++) library, it is hard to know when it will make a difference (since almost any use of the macro will be expanded tointbefore anything further happens).
– Jonathan Leffler
8 hours ago
1
@chris That's the point: Casting -1 to an unsigned type should theoretically yield the maximum representable value of that type (and subsequently behave just fine when right-shifted).
– Max Langhof
8 hours ago
2
Since requirement is "expand to an integer constant expression corresponding to the type uint_leastN_t", I'd expect a cast of whatever is within as in((uint_least8_t) (c))
– chux
8 hours ago
1
@MaxLanghof, My bad, I glossed over the sign mismatch of the value andUINT8_C.
– chris
8 hours ago
|
show 6 more comments
5
In C++ you want to#include <cstdint>, notstdint.h- just saying.
– Jesper Juhl
8 hours ago
2
Implementations can't be controlled by the standard; the implementation can do what it likes, but is supposed to be guided by the standard. Implementations actually do their own thing. It is not hard to argue that the GNU C Library version isn't very accurate, but in a C (as opposed to C++) library, it is hard to know when it will make a difference (since almost any use of the macro will be expanded tointbefore anything further happens).
– Jonathan Leffler
8 hours ago
1
@chris That's the point: Casting -1 to an unsigned type should theoretically yield the maximum representable value of that type (and subsequently behave just fine when right-shifted).
– Max Langhof
8 hours ago
2
Since requirement is "expand to an integer constant expression corresponding to the type uint_leastN_t", I'd expect a cast of whatever is within as in((uint_least8_t) (c))
– chux
8 hours ago
1
@MaxLanghof, My bad, I glossed over the sign mismatch of the value andUINT8_C.
– chris
8 hours ago
5
5
In C++ you want to
#include <cstdint>, not stdint.h - just saying.– Jesper Juhl
8 hours ago
In C++ you want to
#include <cstdint>, not stdint.h - just saying.– Jesper Juhl
8 hours ago
2
2
Implementations can't be controlled by the standard; the implementation can do what it likes, but is supposed to be guided by the standard. Implementations actually do their own thing. It is not hard to argue that the GNU C Library version isn't very accurate, but in a C (as opposed to C++) library, it is hard to know when it will make a difference (since almost any use of the macro will be expanded to
int before anything further happens).– Jonathan Leffler
8 hours ago
Implementations can't be controlled by the standard; the implementation can do what it likes, but is supposed to be guided by the standard. Implementations actually do their own thing. It is not hard to argue that the GNU C Library version isn't very accurate, but in a C (as opposed to C++) library, it is hard to know when it will make a difference (since almost any use of the macro will be expanded to
int before anything further happens).– Jonathan Leffler
8 hours ago
1
1
@chris That's the point: Casting -1 to an unsigned type should theoretically yield the maximum representable value of that type (and subsequently behave just fine when right-shifted).
– Max Langhof
8 hours ago
@chris That's the point: Casting -1 to an unsigned type should theoretically yield the maximum representable value of that type (and subsequently behave just fine when right-shifted).
– Max Langhof
8 hours ago
2
2
Since requirement is "expand to an integer constant expression corresponding to the type uint_leastN_t", I'd expect a cast of whatever is within as in
((uint_least8_t) (c))– chux
8 hours ago
Since requirement is "expand to an integer constant expression corresponding to the type uint_leastN_t", I'd expect a cast of whatever is within as in
((uint_least8_t) (c))– chux
8 hours ago
1
1
@MaxLanghof, My bad, I glossed over the sign mismatch of the value and
UINT8_C.– chris
8 hours ago
@MaxLanghof, My bad, I glossed over the sign mismatch of the value and
UINT8_C.– chris
8 hours ago
|
show 6 more comments
3 Answers
3
active
oldest
votes
If an int can represent all the values of a uint_least8_t then the GNU implementation of the UINT8_C(value) macro as #define UINT8_C(c) c conforms to the C standard.
As per C11 7.20.4 Macros for integer constants paragraph 2:
The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type.
For example, if UINT_LEAST8_MAX is 255, the following usage examples are legal:
UINT8_C(0)UINT8_C(255)UINT8_C(0377)UINT8_C(0xff)
But the following usage examples result in undefined behavior:
UINT8_C(-1)— not an integer constant as defined in 6.4.4.1
UINT8_C(1u)— not an unsuffixed integer constant
UINT8_C(256)— exceeds the limits ofuint_least8_tfor this implementation
The signed equivalent INT8_C(-1) is also undefined behavior for the same reasons.
If UINT_LEAST8_MAX is 255, a legal instance of UINT8_C(value) will expand to an integer constant expression and its type will be int due to integer promotions, as per paragraph 3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
Thus for any legal invocation of UINT8_C(value), the expansion of this to value by any implementation where an int can represent all the values of uint_least8_t is perfectly standard conforming. For any illegal invocation of UINT8_C(value) you may not get the result you were expecting due to undefined behavior.
[EDIT added for completeness] As pointed out in cpplearner's answer, the other implementations of UINT8_C(value) shown in OP's question are invalid because they expand to expressions that are not suitable for use in #if processing directives.
add a comment |
The first two implementations are not conforming to the C standard, because they don't permit UINT8_C(42) in #if directives:
#if UINT8_C(42) == 42 // <- should be a valid expression
N1570 7.20.4/3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
1
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
add a comment |
The GNU C library is not correct. Per C11 7.20.4.1 Macros for minimum-width integer constants UINTN_C(value) is defined as
The macro
UINTN_C(value)shall expand to an integer constant expression corresponding to the typeuint_leastN_t.
So it is not proper the they just use c since c may or may not be a uint_least8_t.
3
At least for the C language (I've no idea about C++), if theuint_least8_tvalue would be promoted to anintanyway, then#define UINT8_C(c) cis fair enough. The unsuffixed integer constantcis required to be within the range ofuint_least8_t(C11 7.20.4p2), so using an out-of-range argument is UB.
– Ian Abbott
7 hours ago
1
But-1is not representable byuint_least8_tso it is UB,.
– Ian Abbott
7 hours ago
1
@IanAbbott That is not correct. Any value is representable in auint8_least_tas it uses modulo 2^8 arithmetic. doing(uint8_least_t)-1give you the max value.
– NathanOliver
7 hours ago
2
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
1
Then it is still UB because-1is not an integer constant as required by 7.20.4p2.
– Ian Abbott
7 hours ago
|
show 7 more comments
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%2f57417154%2fwhy-do-implementations-of-stdint-h-disagree-on-the-definition-of-uint8-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
If an int can represent all the values of a uint_least8_t then the GNU implementation of the UINT8_C(value) macro as #define UINT8_C(c) c conforms to the C standard.
As per C11 7.20.4 Macros for integer constants paragraph 2:
The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type.
For example, if UINT_LEAST8_MAX is 255, the following usage examples are legal:
UINT8_C(0)UINT8_C(255)UINT8_C(0377)UINT8_C(0xff)
But the following usage examples result in undefined behavior:
UINT8_C(-1)— not an integer constant as defined in 6.4.4.1
UINT8_C(1u)— not an unsuffixed integer constant
UINT8_C(256)— exceeds the limits ofuint_least8_tfor this implementation
The signed equivalent INT8_C(-1) is also undefined behavior for the same reasons.
If UINT_LEAST8_MAX is 255, a legal instance of UINT8_C(value) will expand to an integer constant expression and its type will be int due to integer promotions, as per paragraph 3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
Thus for any legal invocation of UINT8_C(value), the expansion of this to value by any implementation where an int can represent all the values of uint_least8_t is perfectly standard conforming. For any illegal invocation of UINT8_C(value) you may not get the result you were expecting due to undefined behavior.
[EDIT added for completeness] As pointed out in cpplearner's answer, the other implementations of UINT8_C(value) shown in OP's question are invalid because they expand to expressions that are not suitable for use in #if processing directives.
add a comment |
If an int can represent all the values of a uint_least8_t then the GNU implementation of the UINT8_C(value) macro as #define UINT8_C(c) c conforms to the C standard.
As per C11 7.20.4 Macros for integer constants paragraph 2:
The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type.
For example, if UINT_LEAST8_MAX is 255, the following usage examples are legal:
UINT8_C(0)UINT8_C(255)UINT8_C(0377)UINT8_C(0xff)
But the following usage examples result in undefined behavior:
UINT8_C(-1)— not an integer constant as defined in 6.4.4.1
UINT8_C(1u)— not an unsuffixed integer constant
UINT8_C(256)— exceeds the limits ofuint_least8_tfor this implementation
The signed equivalent INT8_C(-1) is also undefined behavior for the same reasons.
If UINT_LEAST8_MAX is 255, a legal instance of UINT8_C(value) will expand to an integer constant expression and its type will be int due to integer promotions, as per paragraph 3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
Thus for any legal invocation of UINT8_C(value), the expansion of this to value by any implementation where an int can represent all the values of uint_least8_t is perfectly standard conforming. For any illegal invocation of UINT8_C(value) you may not get the result you were expecting due to undefined behavior.
[EDIT added for completeness] As pointed out in cpplearner's answer, the other implementations of UINT8_C(value) shown in OP's question are invalid because they expand to expressions that are not suitable for use in #if processing directives.
add a comment |
If an int can represent all the values of a uint_least8_t then the GNU implementation of the UINT8_C(value) macro as #define UINT8_C(c) c conforms to the C standard.
As per C11 7.20.4 Macros for integer constants paragraph 2:
The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type.
For example, if UINT_LEAST8_MAX is 255, the following usage examples are legal:
UINT8_C(0)UINT8_C(255)UINT8_C(0377)UINT8_C(0xff)
But the following usage examples result in undefined behavior:
UINT8_C(-1)— not an integer constant as defined in 6.4.4.1
UINT8_C(1u)— not an unsuffixed integer constant
UINT8_C(256)— exceeds the limits ofuint_least8_tfor this implementation
The signed equivalent INT8_C(-1) is also undefined behavior for the same reasons.
If UINT_LEAST8_MAX is 255, a legal instance of UINT8_C(value) will expand to an integer constant expression and its type will be int due to integer promotions, as per paragraph 3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
Thus for any legal invocation of UINT8_C(value), the expansion of this to value by any implementation where an int can represent all the values of uint_least8_t is perfectly standard conforming. For any illegal invocation of UINT8_C(value) you may not get the result you were expecting due to undefined behavior.
[EDIT added for completeness] As pointed out in cpplearner's answer, the other implementations of UINT8_C(value) shown in OP's question are invalid because they expand to expressions that are not suitable for use in #if processing directives.
If an int can represent all the values of a uint_least8_t then the GNU implementation of the UINT8_C(value) macro as #define UINT8_C(c) c conforms to the C standard.
As per C11 7.20.4 Macros for integer constants paragraph 2:
The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type.
For example, if UINT_LEAST8_MAX is 255, the following usage examples are legal:
UINT8_C(0)UINT8_C(255)UINT8_C(0377)UINT8_C(0xff)
But the following usage examples result in undefined behavior:
UINT8_C(-1)— not an integer constant as defined in 6.4.4.1
UINT8_C(1u)— not an unsuffixed integer constant
UINT8_C(256)— exceeds the limits ofuint_least8_tfor this implementation
The signed equivalent INT8_C(-1) is also undefined behavior for the same reasons.
If UINT_LEAST8_MAX is 255, a legal instance of UINT8_C(value) will expand to an integer constant expression and its type will be int due to integer promotions, as per paragraph 3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
Thus for any legal invocation of UINT8_C(value), the expansion of this to value by any implementation where an int can represent all the values of uint_least8_t is perfectly standard conforming. For any illegal invocation of UINT8_C(value) you may not get the result you were expecting due to undefined behavior.
[EDIT added for completeness] As pointed out in cpplearner's answer, the other implementations of UINT8_C(value) shown in OP's question are invalid because they expand to expressions that are not suitable for use in #if processing directives.
edited 5 hours ago
answered 6 hours ago
Ian AbbottIan Abbott
4,1437 silver badges17 bronze badges
4,1437 silver badges17 bronze badges
add a comment |
add a comment |
The first two implementations are not conforming to the C standard, because they don't permit UINT8_C(42) in #if directives:
#if UINT8_C(42) == 42 // <- should be a valid expression
N1570 7.20.4/3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
1
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
add a comment |
The first two implementations are not conforming to the C standard, because they don't permit UINT8_C(42) in #if directives:
#if UINT8_C(42) == 42 // <- should be a valid expression
N1570 7.20.4/3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
1
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
add a comment |
The first two implementations are not conforming to the C standard, because they don't permit UINT8_C(42) in #if directives:
#if UINT8_C(42) == 42 // <- should be a valid expression
N1570 7.20.4/3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
The first two implementations are not conforming to the C standard, because they don't permit UINT8_C(42) in #if directives:
#if UINT8_C(42) == 42 // <- should be a valid expression
N1570 7.20.4/3:
Each invocation of one of these macros shall expand to an integer constant expression suitable for use in
#ifpreprocessing directives. The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. The value of the expression shall be that of the argument.
edited 5 hours ago
answered 6 hours ago
cpplearnercpplearner
6,6342 gold badges26 silver badges47 bronze badges
6,6342 gold badges26 silver badges47 bronze badges
1
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
add a comment |
1
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
1
1
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
In addition, the second one doesn't conform to the C standard because it expands to C++ code.
– Shawn
5 hours ago
add a comment |
The GNU C library is not correct. Per C11 7.20.4.1 Macros for minimum-width integer constants UINTN_C(value) is defined as
The macro
UINTN_C(value)shall expand to an integer constant expression corresponding to the typeuint_leastN_t.
So it is not proper the they just use c since c may or may not be a uint_least8_t.
3
At least for the C language (I've no idea about C++), if theuint_least8_tvalue would be promoted to anintanyway, then#define UINT8_C(c) cis fair enough. The unsuffixed integer constantcis required to be within the range ofuint_least8_t(C11 7.20.4p2), so using an out-of-range argument is UB.
– Ian Abbott
7 hours ago
1
But-1is not representable byuint_least8_tso it is UB,.
– Ian Abbott
7 hours ago
1
@IanAbbott That is not correct. Any value is representable in auint8_least_tas it uses modulo 2^8 arithmetic. doing(uint8_least_t)-1give you the max value.
– NathanOliver
7 hours ago
2
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
1
Then it is still UB because-1is not an integer constant as required by 7.20.4p2.
– Ian Abbott
7 hours ago
|
show 7 more comments
The GNU C library is not correct. Per C11 7.20.4.1 Macros for minimum-width integer constants UINTN_C(value) is defined as
The macro
UINTN_C(value)shall expand to an integer constant expression corresponding to the typeuint_leastN_t.
So it is not proper the they just use c since c may or may not be a uint_least8_t.
3
At least for the C language (I've no idea about C++), if theuint_least8_tvalue would be promoted to anintanyway, then#define UINT8_C(c) cis fair enough. The unsuffixed integer constantcis required to be within the range ofuint_least8_t(C11 7.20.4p2), so using an out-of-range argument is UB.
– Ian Abbott
7 hours ago
1
But-1is not representable byuint_least8_tso it is UB,.
– Ian Abbott
7 hours ago
1
@IanAbbott That is not correct. Any value is representable in auint8_least_tas it uses modulo 2^8 arithmetic. doing(uint8_least_t)-1give you the max value.
– NathanOliver
7 hours ago
2
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
1
Then it is still UB because-1is not an integer constant as required by 7.20.4p2.
– Ian Abbott
7 hours ago
|
show 7 more comments
The GNU C library is not correct. Per C11 7.20.4.1 Macros for minimum-width integer constants UINTN_C(value) is defined as
The macro
UINTN_C(value)shall expand to an integer constant expression corresponding to the typeuint_leastN_t.
So it is not proper the they just use c since c may or may not be a uint_least8_t.
The GNU C library is not correct. Per C11 7.20.4.1 Macros for minimum-width integer constants UINTN_C(value) is defined as
The macro
UINTN_C(value)shall expand to an integer constant expression corresponding to the typeuint_leastN_t.
So it is not proper the they just use c since c may or may not be a uint_least8_t.
answered 8 hours ago
NathanOliverNathanOliver
111k19 gold badges175 silver badges252 bronze badges
111k19 gold badges175 silver badges252 bronze badges
3
At least for the C language (I've no idea about C++), if theuint_least8_tvalue would be promoted to anintanyway, then#define UINT8_C(c) cis fair enough. The unsuffixed integer constantcis required to be within the range ofuint_least8_t(C11 7.20.4p2), so using an out-of-range argument is UB.
– Ian Abbott
7 hours ago
1
But-1is not representable byuint_least8_tso it is UB,.
– Ian Abbott
7 hours ago
1
@IanAbbott That is not correct. Any value is representable in auint8_least_tas it uses modulo 2^8 arithmetic. doing(uint8_least_t)-1give you the max value.
– NathanOliver
7 hours ago
2
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
1
Then it is still UB because-1is not an integer constant as required by 7.20.4p2.
– Ian Abbott
7 hours ago
|
show 7 more comments
3
At least for the C language (I've no idea about C++), if theuint_least8_tvalue would be promoted to anintanyway, then#define UINT8_C(c) cis fair enough. The unsuffixed integer constantcis required to be within the range ofuint_least8_t(C11 7.20.4p2), so using an out-of-range argument is UB.
– Ian Abbott
7 hours ago
1
But-1is not representable byuint_least8_tso it is UB,.
– Ian Abbott
7 hours ago
1
@IanAbbott That is not correct. Any value is representable in auint8_least_tas it uses modulo 2^8 arithmetic. doing(uint8_least_t)-1give you the max value.
– NathanOliver
7 hours ago
2
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
1
Then it is still UB because-1is not an integer constant as required by 7.20.4p2.
– Ian Abbott
7 hours ago
3
3
At least for the C language (I've no idea about C++), if the
uint_least8_t value would be promoted to an int anyway, then #define UINT8_C(c) c is fair enough. The unsuffixed integer constant c is required to be within the range of uint_least8_t (C11 7.20.4p2), so using an out-of-range argument is UB.– Ian Abbott
7 hours ago
At least for the C language (I've no idea about C++), if the
uint_least8_t value would be promoted to an int anyway, then #define UINT8_C(c) c is fair enough. The unsuffixed integer constant c is required to be within the range of uint_least8_t (C11 7.20.4p2), so using an out-of-range argument is UB.– Ian Abbott
7 hours ago
1
1
But
-1 is not representable by uint_least8_t so it is UB,.– Ian Abbott
7 hours ago
But
-1 is not representable by uint_least8_t so it is UB,.– Ian Abbott
7 hours ago
1
1
@IanAbbott That is not correct. Any value is representable in a
uint8_least_t as it uses modulo 2^8 arithmetic. doing (uint8_least_t)-1 give you the max value.– NathanOliver
7 hours ago
@IanAbbott That is not correct. Any value is representable in a
uint8_least_t as it uses modulo 2^8 arithmetic. doing (uint8_least_t)-1 give you the max value.– NathanOliver
7 hours ago
2
2
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
C11 7.20.4p2: "The argument in any instance of these macros shall be an unsuffixed integer constant (as defined in 6.4.4.1) with a value that does not exceed the limits for the corresponding type." (emphasis mine)
– Ian Abbott
7 hours ago
1
1
Then it is still UB because
-1 is not an integer constant as required by 7.20.4p2.– Ian Abbott
7 hours ago
Then it is still UB because
-1 is not an integer constant as required by 7.20.4p2.– Ian Abbott
7 hours ago
|
show 7 more comments
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%2f57417154%2fwhy-do-implementations-of-stdint-h-disagree-on-the-definition-of-uint8-c%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
5
In C++ you want to
#include <cstdint>, notstdint.h- just saying.– Jesper Juhl
8 hours ago
2
Implementations can't be controlled by the standard; the implementation can do what it likes, but is supposed to be guided by the standard. Implementations actually do their own thing. It is not hard to argue that the GNU C Library version isn't very accurate, but in a C (as opposed to C++) library, it is hard to know when it will make a difference (since almost any use of the macro will be expanded to
intbefore anything further happens).– Jonathan Leffler
8 hours ago
1
@chris That's the point: Casting -1 to an unsigned type should theoretically yield the maximum representable value of that type (and subsequently behave just fine when right-shifted).
– Max Langhof
8 hours ago
2
Since requirement is "expand to an integer constant expression corresponding to the type uint_leastN_t", I'd expect a cast of whatever is within as in
((uint_least8_t) (c))– chux
8 hours ago
1
@MaxLanghof, My bad, I glossed over the sign mismatch of the value and
UINT8_C.– chris
8 hours ago