Unexpected types from UINT32_C, UINTN_C











up vote
7
down vote

favorite













7.20.4.1 Macros for minimum-width integer constants

... The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t. For example, if uint_least64_t is a name for the type unsigned long long int, then UINT64_C(0x123) might expand to the integer constant 0x123ULL. C11dr §7.20.4.1 1




The type of UINTN_C() and friends are not as expected. See "Expected" comments in code output.



A) Is my compiler implementation wrong and the constant type should be uint_leastN_t?

or

B) Should the type of constant from UINTN_C(value) be the minimum of uint_leastN_t, int, unsigned and type needed to encode the value?

or

C) something else?





I had expected that the type of the constants to correspond to uint_leastN_t, but it appears to not be so under 2 conditions:



**1 If the macro corresponding type is below int/unsigned, the constant is int/unsigned



**2 If the value exceeds the range of the uint_leastN_t, then the type becomes a wider type constant.




§6.4.4.1 "The type of an integer constant is the first of the corresponding list in which its value can be represented ... (long list follows).






#include <limits.h>
#include <stdio.h>

#define type_of(X) _Generic((X),
unsigned long long: "unsigned long long",
unsigned long: "unsigned long",
unsigned: "unsigned",
int: "int",
unsigned short: "unsigned short",
default: "?"
)

int main() {
uint_least16_t u16 = 0;
uint_least32_t u32 = 0;
uint_least64_t u64 = 0;
printf("%zu %sn", sizeof(u16), type_of(u16));
printf("%zu %sn", sizeof(u32), type_of(u32));
printf("%zu %sn", sizeof(u64), type_of(u64));
puts("");
printf("%zu %sn", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0), type_of(UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234)));
printf("%zu %sn", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345)));
printf("%zu %sn", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678)));
printf("%zu %sn", sizeof UINT32_C(0x123456789), type_of(UINT32_C(0x123456789)));
return 0;

//round_frac_test(-2.05446162500000000e+06, 205);
round_frac_test(fp_rand(), 6);
round_frac_tests(10000);
puts("Done");
return 0;
}


Output



2 unsigned short
4 unsigned
8 unsigned long long

2 unsigned short
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **2
4 unsigned
8 unsigned long long // Expected 4 unsigned, see **2


I am using (GNU C11 (GCC) version 5.4.0)



In forming this post, I am leaning toward B, yet I am looking for your rational for confirmation -one way of the other. If B is so, a disappointing part is that UINTN_C() could result in a signed type.



I suppose that is what the "minimum-width" part is about.










share|improve this question


















  • 1




    I think you have a very valid point. The glibc macros in stdint.h should be e.g. #define UINT16_C(c) ((uint16_t)(c)) and so on, whereas right now they are just #define UINT16_C(c) c (or c # U, c # UL, c # ULL for larger types). Care to file a bug report? It usually only takes about a year for a tested patch to be accepted, and another year or so to dribble down to Linux distributions, in my experience.
    – Nominal Animal
    Aug 2 '17 at 17:14






  • 1




    Could this hinge on the corresponding in "shall expand to an integer constant expression corresponding to the type uint_leastN_t." In §6.2.5 6 there is "For each of the signed integer types, there is a corresponding (but different) unsigned integer type"; that is, maybe a type corresponding to an unsigned integer type need not be unsigned?
    – David Bowling
    Aug 2 '17 at 17:20












  • MSVC isn't much better: #define UINT16_C(x) (x)
    – dbush
    Aug 2 '17 at 17:22










  • @dbush It is intentional
    – P__J__
    Aug 2 '17 at 17:22










  • @NominalAnimal No, that wouldn't be valid, because that wouldn't work in #if expressions.
    – user743382
    Aug 2 '17 at 17:48















up vote
7
down vote

favorite













7.20.4.1 Macros for minimum-width integer constants

... The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t. For example, if uint_least64_t is a name for the type unsigned long long int, then UINT64_C(0x123) might expand to the integer constant 0x123ULL. C11dr §7.20.4.1 1




The type of UINTN_C() and friends are not as expected. See "Expected" comments in code output.



A) Is my compiler implementation wrong and the constant type should be uint_leastN_t?

or

B) Should the type of constant from UINTN_C(value) be the minimum of uint_leastN_t, int, unsigned and type needed to encode the value?

or

C) something else?





I had expected that the type of the constants to correspond to uint_leastN_t, but it appears to not be so under 2 conditions:



**1 If the macro corresponding type is below int/unsigned, the constant is int/unsigned



**2 If the value exceeds the range of the uint_leastN_t, then the type becomes a wider type constant.




§6.4.4.1 "The type of an integer constant is the first of the corresponding list in which its value can be represented ... (long list follows).






#include <limits.h>
#include <stdio.h>

#define type_of(X) _Generic((X),
unsigned long long: "unsigned long long",
unsigned long: "unsigned long",
unsigned: "unsigned",
int: "int",
unsigned short: "unsigned short",
default: "?"
)

int main() {
uint_least16_t u16 = 0;
uint_least32_t u32 = 0;
uint_least64_t u64 = 0;
printf("%zu %sn", sizeof(u16), type_of(u16));
printf("%zu %sn", sizeof(u32), type_of(u32));
printf("%zu %sn", sizeof(u64), type_of(u64));
puts("");
printf("%zu %sn", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0), type_of(UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234)));
printf("%zu %sn", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345)));
printf("%zu %sn", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678)));
printf("%zu %sn", sizeof UINT32_C(0x123456789), type_of(UINT32_C(0x123456789)));
return 0;

//round_frac_test(-2.05446162500000000e+06, 205);
round_frac_test(fp_rand(), 6);
round_frac_tests(10000);
puts("Done");
return 0;
}


Output



2 unsigned short
4 unsigned
8 unsigned long long

2 unsigned short
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **2
4 unsigned
8 unsigned long long // Expected 4 unsigned, see **2


I am using (GNU C11 (GCC) version 5.4.0)



In forming this post, I am leaning toward B, yet I am looking for your rational for confirmation -one way of the other. If B is so, a disappointing part is that UINTN_C() could result in a signed type.



I suppose that is what the "minimum-width" part is about.










share|improve this question


















  • 1




    I think you have a very valid point. The glibc macros in stdint.h should be e.g. #define UINT16_C(c) ((uint16_t)(c)) and so on, whereas right now they are just #define UINT16_C(c) c (or c # U, c # UL, c # ULL for larger types). Care to file a bug report? It usually only takes about a year for a tested patch to be accepted, and another year or so to dribble down to Linux distributions, in my experience.
    – Nominal Animal
    Aug 2 '17 at 17:14






  • 1




    Could this hinge on the corresponding in "shall expand to an integer constant expression corresponding to the type uint_leastN_t." In §6.2.5 6 there is "For each of the signed integer types, there is a corresponding (but different) unsigned integer type"; that is, maybe a type corresponding to an unsigned integer type need not be unsigned?
    – David Bowling
    Aug 2 '17 at 17:20












  • MSVC isn't much better: #define UINT16_C(x) (x)
    – dbush
    Aug 2 '17 at 17:22










  • @dbush It is intentional
    – P__J__
    Aug 2 '17 at 17:22










  • @NominalAnimal No, that wouldn't be valid, because that wouldn't work in #if expressions.
    – user743382
    Aug 2 '17 at 17:48













up vote
7
down vote

favorite









up vote
7
down vote

favorite












7.20.4.1 Macros for minimum-width integer constants

... The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t. For example, if uint_least64_t is a name for the type unsigned long long int, then UINT64_C(0x123) might expand to the integer constant 0x123ULL. C11dr §7.20.4.1 1




The type of UINTN_C() and friends are not as expected. See "Expected" comments in code output.



A) Is my compiler implementation wrong and the constant type should be uint_leastN_t?

or

B) Should the type of constant from UINTN_C(value) be the minimum of uint_leastN_t, int, unsigned and type needed to encode the value?

or

C) something else?





I had expected that the type of the constants to correspond to uint_leastN_t, but it appears to not be so under 2 conditions:



**1 If the macro corresponding type is below int/unsigned, the constant is int/unsigned



**2 If the value exceeds the range of the uint_leastN_t, then the type becomes a wider type constant.




§6.4.4.1 "The type of an integer constant is the first of the corresponding list in which its value can be represented ... (long list follows).






#include <limits.h>
#include <stdio.h>

#define type_of(X) _Generic((X),
unsigned long long: "unsigned long long",
unsigned long: "unsigned long",
unsigned: "unsigned",
int: "int",
unsigned short: "unsigned short",
default: "?"
)

int main() {
uint_least16_t u16 = 0;
uint_least32_t u32 = 0;
uint_least64_t u64 = 0;
printf("%zu %sn", sizeof(u16), type_of(u16));
printf("%zu %sn", sizeof(u32), type_of(u32));
printf("%zu %sn", sizeof(u64), type_of(u64));
puts("");
printf("%zu %sn", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0), type_of(UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234)));
printf("%zu %sn", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345)));
printf("%zu %sn", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678)));
printf("%zu %sn", sizeof UINT32_C(0x123456789), type_of(UINT32_C(0x123456789)));
return 0;

//round_frac_test(-2.05446162500000000e+06, 205);
round_frac_test(fp_rand(), 6);
round_frac_tests(10000);
puts("Done");
return 0;
}


Output



2 unsigned short
4 unsigned
8 unsigned long long

2 unsigned short
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **2
4 unsigned
8 unsigned long long // Expected 4 unsigned, see **2


I am using (GNU C11 (GCC) version 5.4.0)



In forming this post, I am leaning toward B, yet I am looking for your rational for confirmation -one way of the other. If B is so, a disappointing part is that UINTN_C() could result in a signed type.



I suppose that is what the "minimum-width" part is about.










share|improve this question














7.20.4.1 Macros for minimum-width integer constants

... The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t. For example, if uint_least64_t is a name for the type unsigned long long int, then UINT64_C(0x123) might expand to the integer constant 0x123ULL. C11dr §7.20.4.1 1




The type of UINTN_C() and friends are not as expected. See "Expected" comments in code output.



A) Is my compiler implementation wrong and the constant type should be uint_leastN_t?

or

B) Should the type of constant from UINTN_C(value) be the minimum of uint_leastN_t, int, unsigned and type needed to encode the value?

or

C) something else?





I had expected that the type of the constants to correspond to uint_leastN_t, but it appears to not be so under 2 conditions:



**1 If the macro corresponding type is below int/unsigned, the constant is int/unsigned



**2 If the value exceeds the range of the uint_leastN_t, then the type becomes a wider type constant.




§6.4.4.1 "The type of an integer constant is the first of the corresponding list in which its value can be represented ... (long list follows).






#include <limits.h>
#include <stdio.h>

#define type_of(X) _Generic((X),
unsigned long long: "unsigned long long",
unsigned long: "unsigned long",
unsigned: "unsigned",
int: "int",
unsigned short: "unsigned short",
default: "?"
)

int main() {
uint_least16_t u16 = 0;
uint_least32_t u32 = 0;
uint_least64_t u64 = 0;
printf("%zu %sn", sizeof(u16), type_of(u16));
printf("%zu %sn", sizeof(u32), type_of(u32));
printf("%zu %sn", sizeof(u64), type_of(u64));
puts("");
printf("%zu %sn", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0), type_of(UINT16_C(0)));
printf("%zu %sn", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234)));
printf("%zu %sn", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345)));
printf("%zu %sn", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678)));
printf("%zu %sn", sizeof UINT32_C(0x123456789), type_of(UINT32_C(0x123456789)));
return 0;

//round_frac_test(-2.05446162500000000e+06, 205);
round_frac_test(fp_rand(), 6);
round_frac_tests(10000);
puts("Done");
return 0;
}


Output



2 unsigned short
4 unsigned
8 unsigned long long

2 unsigned short
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **1
4 int // Expected 2 unsigned short, see **2
4 unsigned
8 unsigned long long // Expected 4 unsigned, see **2


I am using (GNU C11 (GCC) version 5.4.0)



In forming this post, I am leaning toward B, yet I am looking for your rational for confirmation -one way of the other. If B is so, a disappointing part is that UINTN_C() could result in a signed type.



I suppose that is what the "minimum-width" part is about.







c language-lawyer






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Aug 2 '17 at 16:46









chux

78.8k869144




78.8k869144








  • 1




    I think you have a very valid point. The glibc macros in stdint.h should be e.g. #define UINT16_C(c) ((uint16_t)(c)) and so on, whereas right now they are just #define UINT16_C(c) c (or c # U, c # UL, c # ULL for larger types). Care to file a bug report? It usually only takes about a year for a tested patch to be accepted, and another year or so to dribble down to Linux distributions, in my experience.
    – Nominal Animal
    Aug 2 '17 at 17:14






  • 1




    Could this hinge on the corresponding in "shall expand to an integer constant expression corresponding to the type uint_leastN_t." In §6.2.5 6 there is "For each of the signed integer types, there is a corresponding (but different) unsigned integer type"; that is, maybe a type corresponding to an unsigned integer type need not be unsigned?
    – David Bowling
    Aug 2 '17 at 17:20












  • MSVC isn't much better: #define UINT16_C(x) (x)
    – dbush
    Aug 2 '17 at 17:22










  • @dbush It is intentional
    – P__J__
    Aug 2 '17 at 17:22










  • @NominalAnimal No, that wouldn't be valid, because that wouldn't work in #if expressions.
    – user743382
    Aug 2 '17 at 17:48














  • 1




    I think you have a very valid point. The glibc macros in stdint.h should be e.g. #define UINT16_C(c) ((uint16_t)(c)) and so on, whereas right now they are just #define UINT16_C(c) c (or c # U, c # UL, c # ULL for larger types). Care to file a bug report? It usually only takes about a year for a tested patch to be accepted, and another year or so to dribble down to Linux distributions, in my experience.
    – Nominal Animal
    Aug 2 '17 at 17:14






  • 1




    Could this hinge on the corresponding in "shall expand to an integer constant expression corresponding to the type uint_leastN_t." In §6.2.5 6 there is "For each of the signed integer types, there is a corresponding (but different) unsigned integer type"; that is, maybe a type corresponding to an unsigned integer type need not be unsigned?
    – David Bowling
    Aug 2 '17 at 17:20












  • MSVC isn't much better: #define UINT16_C(x) (x)
    – dbush
    Aug 2 '17 at 17:22










  • @dbush It is intentional
    – P__J__
    Aug 2 '17 at 17:22










  • @NominalAnimal No, that wouldn't be valid, because that wouldn't work in #if expressions.
    – user743382
    Aug 2 '17 at 17:48








1




1




I think you have a very valid point. The glibc macros in stdint.h should be e.g. #define UINT16_C(c) ((uint16_t)(c)) and so on, whereas right now they are just #define UINT16_C(c) c (or c # U, c # UL, c # ULL for larger types). Care to file a bug report? It usually only takes about a year for a tested patch to be accepted, and another year or so to dribble down to Linux distributions, in my experience.
– Nominal Animal
Aug 2 '17 at 17:14




I think you have a very valid point. The glibc macros in stdint.h should be e.g. #define UINT16_C(c) ((uint16_t)(c)) and so on, whereas right now they are just #define UINT16_C(c) c (or c # U, c # UL, c # ULL for larger types). Care to file a bug report? It usually only takes about a year for a tested patch to be accepted, and another year or so to dribble down to Linux distributions, in my experience.
– Nominal Animal
Aug 2 '17 at 17:14




1




1




Could this hinge on the corresponding in "shall expand to an integer constant expression corresponding to the type uint_leastN_t." In §6.2.5 6 there is "For each of the signed integer types, there is a corresponding (but different) unsigned integer type"; that is, maybe a type corresponding to an unsigned integer type need not be unsigned?
– David Bowling
Aug 2 '17 at 17:20






Could this hinge on the corresponding in "shall expand to an integer constant expression corresponding to the type uint_leastN_t." In §6.2.5 6 there is "For each of the signed integer types, there is a corresponding (but different) unsigned integer type"; that is, maybe a type corresponding to an unsigned integer type need not be unsigned?
– David Bowling
Aug 2 '17 at 17:20














MSVC isn't much better: #define UINT16_C(x) (x)
– dbush
Aug 2 '17 at 17:22




MSVC isn't much better: #define UINT16_C(x) (x)
– dbush
Aug 2 '17 at 17:22












@dbush It is intentional
– P__J__
Aug 2 '17 at 17:22




@dbush It is intentional
– P__J__
Aug 2 '17 at 17:22












@NominalAnimal No, that wouldn't be valid, because that wouldn't work in #if expressions.
– user743382
Aug 2 '17 at 17:48




@NominalAnimal No, that wouldn't be valid, because that wouldn't work in #if expressions.
– user743382
Aug 2 '17 at 17:48












2 Answers
2






active

oldest

votes

















up vote
11
down vote



accepted










This is covered in the parent subsection, 7.20.4.



In the portion you quoted:




The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.




it says "corresponding to", not that the expansion is actually of that type. The meaning of "corresponding to" is explained in 7.20.4p3:




Each invocation of one of these macros shall expand to an integer
constant expression suitable for use in #if preprocessing 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.




Since the macros are intended to be used in an #if directive, they cannot use casts (the preprocessor doesn't understand casts or type names).



In practice, such a constant expression will almost always be implicitly converted to the appropriate type, so the fact that its actual type differs from what you might expect is not generally a problem.



As for a value outside the range of uint_leastN_t, that's also covered in the parent subsection, in 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.




This is a "shall" outside a constraint, so violating it causes undefined behavior. Don't do that.



(When reading the C standard, it's generally a good idea to check the parent subsections for wording that might clarify or override what you're reading. I've been bitten by this myself.)






share|improve this answer























  • The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
    – chux
    Aug 2 '17 at 17:48










  • ... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
    – chux
    Aug 2 '17 at 18:02


















up vote
0
down vote













On the host with 16 bit short and 32 bit integers unsigned short numbers are promoted to int. So the those macros are defined as:



#define INT16_C(x) (x)
#define UINT16_C(x) (x)


with no 'U' suffix for the unsigned short




If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;




Those macros do only expand to the corresponding constants (or integer literals using more common language), and do not create any objects, and have to usable in the #if. So no casts are allowed. Macros do not perform any range checks as well.



int16_t x0 = 123;
uint16_t x1 = 123; // no sign suffix needed
int32_t x2 = 2147483647;
uint32_t x3 = 2147583647U; //sign suffix theoreticaly needed as int and unsigned int have the same rank
int64_t x4 = 9223372036854775807LL;
uint64_t x5 = 9237372036854775807ULL; //same as above





share|improve this answer























  • Where is your quote from? I’m surprised that conversion happens for constants.
    – Daniel H
    Aug 2 '17 at 17:45










  • 'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
    – P__J__
    Aug 2 '17 at 17:49












  • Yeah, that’s the relevant part I was missing.
    – Daniel H
    Aug 2 '17 at 18:04











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',
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
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f45466601%2funexpected-types-from-uint32-c-uintn-c%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








up vote
11
down vote



accepted










This is covered in the parent subsection, 7.20.4.



In the portion you quoted:




The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.




it says "corresponding to", not that the expansion is actually of that type. The meaning of "corresponding to" is explained in 7.20.4p3:




Each invocation of one of these macros shall expand to an integer
constant expression suitable for use in #if preprocessing 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.




Since the macros are intended to be used in an #if directive, they cannot use casts (the preprocessor doesn't understand casts or type names).



In practice, such a constant expression will almost always be implicitly converted to the appropriate type, so the fact that its actual type differs from what you might expect is not generally a problem.



As for a value outside the range of uint_leastN_t, that's also covered in the parent subsection, in 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.




This is a "shall" outside a constraint, so violating it causes undefined behavior. Don't do that.



(When reading the C standard, it's generally a good idea to check the parent subsections for wording that might clarify or override what you're reading. I've been bitten by this myself.)






share|improve this answer























  • The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
    – chux
    Aug 2 '17 at 17:48










  • ... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
    – chux
    Aug 2 '17 at 18:02















up vote
11
down vote



accepted










This is covered in the parent subsection, 7.20.4.



In the portion you quoted:




The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.




it says "corresponding to", not that the expansion is actually of that type. The meaning of "corresponding to" is explained in 7.20.4p3:




Each invocation of one of these macros shall expand to an integer
constant expression suitable for use in #if preprocessing 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.




Since the macros are intended to be used in an #if directive, they cannot use casts (the preprocessor doesn't understand casts or type names).



In practice, such a constant expression will almost always be implicitly converted to the appropriate type, so the fact that its actual type differs from what you might expect is not generally a problem.



As for a value outside the range of uint_leastN_t, that's also covered in the parent subsection, in 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.




This is a "shall" outside a constraint, so violating it causes undefined behavior. Don't do that.



(When reading the C standard, it's generally a good idea to check the parent subsections for wording that might clarify or override what you're reading. I've been bitten by this myself.)






share|improve this answer























  • The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
    – chux
    Aug 2 '17 at 17:48










  • ... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
    – chux
    Aug 2 '17 at 18:02













up vote
11
down vote



accepted







up vote
11
down vote



accepted






This is covered in the parent subsection, 7.20.4.



In the portion you quoted:




The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.




it says "corresponding to", not that the expansion is actually of that type. The meaning of "corresponding to" is explained in 7.20.4p3:




Each invocation of one of these macros shall expand to an integer
constant expression suitable for use in #if preprocessing 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.




Since the macros are intended to be used in an #if directive, they cannot use casts (the preprocessor doesn't understand casts or type names).



In practice, such a constant expression will almost always be implicitly converted to the appropriate type, so the fact that its actual type differs from what you might expect is not generally a problem.



As for a value outside the range of uint_leastN_t, that's also covered in the parent subsection, in 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.




This is a "shall" outside a constraint, so violating it causes undefined behavior. Don't do that.



(When reading the C standard, it's generally a good idea to check the parent subsections for wording that might clarify or override what you're reading. I've been bitten by this myself.)






share|improve this answer














This is covered in the parent subsection, 7.20.4.



In the portion you quoted:




The macro UINTN_C(value) shall expand to an integer constant expression corresponding to the type uint_leastN_t.




it says "corresponding to", not that the expansion is actually of that type. The meaning of "corresponding to" is explained in 7.20.4p3:




Each invocation of one of these macros shall expand to an integer
constant expression suitable for use in #if preprocessing 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.




Since the macros are intended to be used in an #if directive, they cannot use casts (the preprocessor doesn't understand casts or type names).



In practice, such a constant expression will almost always be implicitly converted to the appropriate type, so the fact that its actual type differs from what you might expect is not generally a problem.



As for a value outside the range of uint_leastN_t, that's also covered in the parent subsection, in 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.




This is a "shall" outside a constraint, so violating it causes undefined behavior. Don't do that.



(When reading the C standard, it's generally a good idea to check the parent subsections for wording that might clarify or override what you're reading. I've been bitten by this myself.)







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 10 at 22:38

























answered Aug 2 '17 at 17:44









Keith Thompson

188k25272465




188k25272465












  • The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
    – chux
    Aug 2 '17 at 17:48










  • ... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
    – chux
    Aug 2 '17 at 18:02


















  • The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
    – chux
    Aug 2 '17 at 17:48










  • ... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
    – chux
    Aug 2 '17 at 18:02
















The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
– chux
Aug 2 '17 at 17:48




The "The type of the expression shall have the same type as would an expression of the corresponding type converted according to the integer promotions. " certainly explains the "**1" of the question.
– chux
Aug 2 '17 at 17:48












... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
– chux
Aug 2 '17 at 18:02




... and 7.20.4p2: explains "**2". Hmmm " check the parent" sounds like advice of years ago.
– chux
Aug 2 '17 at 18:02












up vote
0
down vote













On the host with 16 bit short and 32 bit integers unsigned short numbers are promoted to int. So the those macros are defined as:



#define INT16_C(x) (x)
#define UINT16_C(x) (x)


with no 'U' suffix for the unsigned short




If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;




Those macros do only expand to the corresponding constants (or integer literals using more common language), and do not create any objects, and have to usable in the #if. So no casts are allowed. Macros do not perform any range checks as well.



int16_t x0 = 123;
uint16_t x1 = 123; // no sign suffix needed
int32_t x2 = 2147483647;
uint32_t x3 = 2147583647U; //sign suffix theoreticaly needed as int and unsigned int have the same rank
int64_t x4 = 9223372036854775807LL;
uint64_t x5 = 9237372036854775807ULL; //same as above





share|improve this answer























  • Where is your quote from? I’m surprised that conversion happens for constants.
    – Daniel H
    Aug 2 '17 at 17:45










  • 'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
    – P__J__
    Aug 2 '17 at 17:49












  • Yeah, that’s the relevant part I was missing.
    – Daniel H
    Aug 2 '17 at 18:04















up vote
0
down vote













On the host with 16 bit short and 32 bit integers unsigned short numbers are promoted to int. So the those macros are defined as:



#define INT16_C(x) (x)
#define UINT16_C(x) (x)


with no 'U' suffix for the unsigned short




If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;




Those macros do only expand to the corresponding constants (or integer literals using more common language), and do not create any objects, and have to usable in the #if. So no casts are allowed. Macros do not perform any range checks as well.



int16_t x0 = 123;
uint16_t x1 = 123; // no sign suffix needed
int32_t x2 = 2147483647;
uint32_t x3 = 2147583647U; //sign suffix theoreticaly needed as int and unsigned int have the same rank
int64_t x4 = 9223372036854775807LL;
uint64_t x5 = 9237372036854775807ULL; //same as above





share|improve this answer























  • Where is your quote from? I’m surprised that conversion happens for constants.
    – Daniel H
    Aug 2 '17 at 17:45










  • 'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
    – P__J__
    Aug 2 '17 at 17:49












  • Yeah, that’s the relevant part I was missing.
    – Daniel H
    Aug 2 '17 at 18:04













up vote
0
down vote










up vote
0
down vote









On the host with 16 bit short and 32 bit integers unsigned short numbers are promoted to int. So the those macros are defined as:



#define INT16_C(x) (x)
#define UINT16_C(x) (x)


with no 'U' suffix for the unsigned short




If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;




Those macros do only expand to the corresponding constants (or integer literals using more common language), and do not create any objects, and have to usable in the #if. So no casts are allowed. Macros do not perform any range checks as well.



int16_t x0 = 123;
uint16_t x1 = 123; // no sign suffix needed
int32_t x2 = 2147483647;
uint32_t x3 = 2147583647U; //sign suffix theoreticaly needed as int and unsigned int have the same rank
int64_t x4 = 9223372036854775807LL;
uint64_t x5 = 9237372036854775807ULL; //same as above





share|improve this answer














On the host with 16 bit short and 32 bit integers unsigned short numbers are promoted to int. So the those macros are defined as:



#define INT16_C(x) (x)
#define UINT16_C(x) (x)


with no 'U' suffix for the unsigned short




If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;




Those macros do only expand to the corresponding constants (or integer literals using more common language), and do not create any objects, and have to usable in the #if. So no casts are allowed. Macros do not perform any range checks as well.



int16_t x0 = 123;
uint16_t x1 = 123; // no sign suffix needed
int32_t x2 = 2147483647;
uint32_t x3 = 2147583647U; //sign suffix theoreticaly needed as int and unsigned int have the same rank
int64_t x4 = 9223372036854775807LL;
uint64_t x5 = 9237372036854775807ULL; //same as above






share|improve this answer














share|improve this answer



share|improve this answer








edited Aug 2 '17 at 17:54

























answered Aug 2 '17 at 17:21









P__J__

1




1












  • Where is your quote from? I’m surprised that conversion happens for constants.
    – Daniel H
    Aug 2 '17 at 17:45










  • 'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
    – P__J__
    Aug 2 '17 at 17:49












  • Yeah, that’s the relevant part I was missing.
    – Daniel H
    Aug 2 '17 at 18:04


















  • Where is your quote from? I’m surprised that conversion happens for constants.
    – Daniel H
    Aug 2 '17 at 17:45










  • 'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
    – P__J__
    Aug 2 '17 at 17:49












  • Yeah, that’s the relevant part I was missing.
    – Daniel H
    Aug 2 '17 at 18:04
















Where is your quote from? I’m surprised that conversion happens for constants.
– Daniel H
Aug 2 '17 at 17:45




Where is your quote from? I’m surprised that conversion happens for constants.
– Daniel H
Aug 2 '17 at 17:45












'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
– P__J__
Aug 2 '17 at 17:49






'Each invocation of one of these macros shall expand to an integer constant expression suitable for use in #if preprocessing 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.' And then it is from the integer promotion rules. I hope that is enough
– P__J__
Aug 2 '17 at 17:49














Yeah, that’s the relevant part I was missing.
– Daniel H
Aug 2 '17 at 18:04




Yeah, that’s the relevant part I was missing.
– Daniel H
Aug 2 '17 at 18:04


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f45466601%2funexpected-types-from-uint32-c-uintn-c%23new-answer', 'question_page');
}
);

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







Popular posts from this blog

Florida Star v. B. J. F.

Error while running script in elastic search , gateway timeout

Adding quotations to stringified JSON object values