Thank you for explaining that, Lasse. I went ahead and added 'u' suffixes to every macro starting with 0xf and included an explanation in the patch detailing why I think that's a good choice.
I also added #include <_mingw.h> to make _WIN64 get more reliably defined on Cygwin. See the new patch attached to this email. Thanks! --David On Wed, Feb 25, 2026 at 9:53 AM Lasse Collin <[email protected]> wrote: > On 2026-02-25 David Grayson wrote: > > On Wed, Feb 25, 2026 at 12:47 AM LIU Hao <[email protected]> wrote: > > > > > > +#define UINT32_MAX 0xffffffff > > > > +#define UINT_MAX 0xffffffff > > > > > > ... why no `u` here? > > > > > > > For all these macros, I decided to use no suffix if possible. A > > suffix is not needed here because in the C99 specification the type > > of an unsuffixed hexadecimal constant will be the first type in this > > list that can represent it: > > > > 1. int > > 2. unsigned int > > 3. long int > > 4. unsigned long int > > 5. long long int > > 6. unsigned long long int > > > > So in the systems we are targeting, 0xffffffff will be an unsigned > > int since it cannot be represented by an int. If you want a suffix > > for clarity, I can add one, but I don't think it's necessary. > > However, I do use ull instead of ll in macros like ULONGLONG_MAX > > because I don't want readers to see ll and assume the type is simply > > long long. > > All this is correct except in the preprocessor. Since C99, preprocessor > treats integers as if they were intmax_t or uintmax_t. See C99 6.10.1p3 > or C11 6.10.1p4. The footnote in both standards explains it well: > > Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is > 0xFFFF, the constant 0x8000 is signed and positive within a #if > expression even though it would be unsigned in translation phase 7. > > Try: > > #include <stdio.h> > > #define FOO 0xffffffff > #define BAR 0xffffffffu > > int > main(void) > { > puts("" > #if FOO - FOO - 1 > 0 > "FOO - FOO - 1 > 0\n" > #endif > #if BAR - BAR - 1 > 0 > "BAR - BAR - 1 > 0\n" > #endif > ); > > return 0; > } > > It will only print the line with BAR. > > The promoted type of UINT_MAX is unsigned int, so it makes sense that > it behaves like uintmax_t (not intmax_t) in preprocessor. I didn't spot > where the standards say this though. In any case, UINT_MAX and > UINT32_MAX have the U suffix in a few other C libraries. > > -- > Lasse Collin >
From 2ebc071ca9484f4e87ede47ec9f8b24828b94399 Mon Sep 17 00:00:00 2001 From: David Grayson <[email protected]> Date: Tue, 24 Feb 2026 17:33:41 -0800 Subject: [PATCH] headers/intsafe: Add missing MIN/MAX macros. I tested this with my test suite at https://github.com/DavidEGrayson/intsafe to make sure the values and types are correct in 32-bit/64-bit MinGW and 64-bit Cygwin environments. Potential compatibility issues: - The types of smaller macros like UINT8_MAX are 'int', which is different from Microsoft's intsafe.h, but follows the C specification and allows the preprocessor to understand the macro's numeric value. - LONG_MIN, LONG_MAX, and ULONG_MAX describe 'long' and 'unsigned long', whereas native Windows code might expect them to describe LONG and ULONG, which sometimes have a different size. - 128-bit macros from the Microsoft header are not yet supported. - Some of these definitions are different than what we have in stdint.h, limits.h, and cfgmgr32.h, so I'd like to submit a patch for those later if this is acceptd. To keep things consistent and simple, I followed these rules: - A macro does not refer to another macro unless it saves a line of code. Chains of macros are hard to debug because other included headers could break the chain by redefining any macro in the chain. - Only use decimal if it makes the number shorter (otherwise use hex). - Don't use uppercase hex digits. - Don't use uppercase suffixes (for compatibility with __MSABI_LONG). - Only use 'l' and 'll' suffixes if necessary. - Use a 'u' suffix on any unsigned macro that has a 'l' or 'll' suffix, to make it clear what the type is. - Use a 'u' suffix on any macro describing an unsigned type with 32 bits or more. This ensures those macros will be treated as unsigned in the preprocessor, avoiding surprising situations where macros with the same value like ULONG_MAX and UINT32_MAX are treated differently. - Only use subtraction if necessary. Signed-off-by: David Grayson <[email protected]> --- mingw-w64-headers/include/intsafe.h | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/mingw-w64-headers/include/intsafe.h b/mingw-w64-headers/include/intsafe.h index 17f3bda1e..0383cf9e3 100644 --- a/mingw-w64-headers/include/intsafe.h +++ b/mingw-w64-headers/include/intsafe.h @@ -11,9 +11,76 @@ #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) +#include <_mingw.h> #include <wtypesbase.h> #include <specstrings.h> +#define INT8_MIN (-128) +#define INT8_MAX 127 +#define UINT8_MAX 255 +#define BYTE_MAX 255 +#define INT16_MIN (-32768) +#define INT16_MAX 32767 +#define SHORT_MIN (-32768) +#define SHORT_MAX 32767 +#define UINT16_MAX 65535 +#define USHORT_MAX 65535 +#define WORD_MAX 65535 +#define INT32_MIN (-0x7fffffff - 1) +#define INT32_MAX 0x7fffffff +#define INT_MIN (-0x7fffffff - 1) +#define INT_MAX 0x7fffffff +#define UINT32_MAX 0xffffffffu +#define UINT_MAX 0xffffffffu +#define DWORD_MAX __MSABI_LONG(0xffffffffu) +#define INT64_MIN (-0x7fffffffffffffff - 1) +#define INT64_MAX 0x7fffffffffffffff +#define LONGLONG_MIN (-0x7fffffffffffffffll - 1) +#define LONG64_MIN (-0x7fffffffffffffffll - 1) +#define LONGLONG_MAX 0x7fffffffffffffffll +#define LONG64_MAX 0x7fffffffffffffffll +#define UINT64_MAX 0xffffffffffffffffu +#define ULONGLONG_MAX 0xffffffffffffffffull +#define ULONG64_MAX 0xffffffffffffffffull +#define DWORDLONG_MAX 0xffffffffffffffffull +#define DWORD64_MAX 0xffffffffffffffffull + +#ifdef __LP64__ +#define LONG_MIN (-0x7fffffffffffffff - 1) +#define LONG_MAX 0x7fffffffffffffff +#define ULONG_MAX 0xffffffffffffffffu +#else +#define LONG_MIN (-0x7fffffffl - 1) +#define LONG_MAX 0x7fffffffl +#define ULONG_MAX 0xfffffffful +#endif + +#ifdef _WIN64 +#define PTRDIFF_T_MIN (-0x7fffffffffffffff - 1) +#define PTRDIFF_T_MAX 0x7fffffffffffffff +#define SIZE_T_MAX 0xffffffffffffffffu +#define INT_PTR_MIN (-0x7fffffffffffffffll - 1) +#define INT_PTR_MAX 0x7fffffffffffffffll +#define UINT_PTR_MAX 0xffffffffffffffffull +#define LONG_PTR_MIN (-0x7fffffffffffffffll - 1) +#define LONG_PTR_MAX 0x7fffffffffffffffll +#define ULONG_PTR_MAX 0xffffffffffffffffull +#else +#define PTRDIFF_T_MIN (-0x7fffffff - 1) +#define PTRDIFF_T_MAX 0x7fffffff +#define SIZE_T_MAX 0xffffffffu +#define INT_PTR_MIN (-0x7fffffff - 1) +#define INT_PTR_MAX 0x7fffffff +#define UINT_PTR_MAX 0xffffffffu +#define LONG_PTR_MIN (-0x7fffffffl - 1) +#define LONG_PTR_MAX 0x7fffffffl +#define ULONG_PTR_MAX 0xfffffffful +#endif +#define SSIZE_T_MIN LONG_PTR_MIN +#define SSIZE_T_MAX LONG_PTR_MAX +#define _SIZE_T_MAX ULONG_PTR_MAX +#define DWORD_PTR_MAX ULONG_PTR_MAX + #define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216) #ifndef S_OK -- 2.52.0
_______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
