Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 459 Vote(s) - 3.54 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Unexpected types from UINT32_C, UINTN_C

#1
> **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 %s\n", sizeof(u16), type_of(u16));
printf("%zu %s\n", sizeof(u32), type_of(u32));
printf("%zu %s\n", sizeof(u64), type_of(u64));
puts("");
printf("%zu %s\n", sizeof((uint_least16_t) UINT16_C(0)), type_of((uint_least16_t) UINT16_C(0)));
printf("%zu %s\n", sizeof UINT16_C(0), type_of(UINT16_C(0)));
printf("%zu %s\n", sizeof UINT16_C(0x1234), type_of(UINT16_C(0x1234)));
printf("%zu %s\n", sizeof UINT16_C(0x12345), type_of(UINT16_C(0x12345)));
printf("%zu %s\n", sizeof UINT32_C(0x12345678), type_of(UINT32_C(0x12345678)));
printf("%zu %s\n", 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.
Reply

#2
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
Reply

#3
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.)
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through