News:

Download Pelles C here: http://www.pellesc.se

Main Menu

Recent posts

#61
User contributions / Re: Import libraries for the U...
Last post by Vortex - February 09, 2026, 12:30:20 PM
Hi Timo,

I will try it with the latest release of Polink.
#62
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by TimoVJL - February 09, 2026, 11:18:26 AM
That silly test used only ucrtbase.dll, as those Api Stub forwanders mostly point to it.
Making ucrt.lib is more demanding, as have to collect those (stupid) forwanders are mostly used for versioning, and with no code.
#63
User contributions / Re: Import libraries for the U...
Last post by TimoVJL - February 09, 2026, 11:12:01 AM
Is it possible to build that ucrt.lib with polib.exe too ?
#64
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by jack - February 08, 2026, 06:26:31 PM
thanks Vortex
#65
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by Vortex - February 08, 2026, 06:06:16 PM
Hi Jack,

It's easy to build and use the import library for ucrt :

Import libraries for the Universal C Runtime :

https://forum.pellesc.de/index.php?topic=11052.0

Universal C Runtime example :

https://forum.pellesc.de/index.php?topic=11054.0
#66
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by TimoVJL - February 08, 2026, 03:33:53 PM
We can test this too ?
...
static unsigned __int64 _OptionsStorage; // local option storage
...
psprintf(((ULONGLONG)&_OptionsStorage|_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR), buf, sizeof(buf), fmt, NULL, vl);
...
#67
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by jack - February 08, 2026, 01:49:28 PM
with uppercase option D I get a bit more info
0000000140005048 <options>:
   140005048: 24 00                and    al,0x0
   14000504a: 00 00                add    BYTE PTR [rax],al
   14000504c: 00 00                add    BYTE PTR [rax],al
...
#68
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by jack - February 08, 2026, 01:34:15 PM
Quote from: TimoVJL on February 08, 2026, 01:12:09 PMA that <options> is a local storage ?
that is my guess
#69
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by TimoVJL - February 08, 2026, 01:12:09 PM
A that <options> is a local storage ?
#if _CRT_FUNCTIONS_REQUIRED
    // This function must not be inlined into callers to avoid ODR violations.  The
    // static local variable has different names in C and in C++ translation units.
    _Check_return_ _Ret_notnull_
    _CRT_INLINE_PURE_SECURITYCRITICAL_ATTRIBUTE
    __declspec(noinline) __inline unsigned __int64* __CRTDECL __local_stdio_printf_options(void)
    {
        static unsigned __int64 _OptionsStorage;
        return &_OptionsStorage;
    }

    // This function must not be inlined into callers to avoid ODR violations.  The
    // static local variable has different names in C and in C++ translation units.
    _Check_return_ _Ret_notnull_
    _CRT_INLINE_PURE_SECURITYCRITICAL_ATTRIBUTE
    __declspec(noinline) __inline unsigned __int64* __CRTDECL __local_stdio_scanf_options(void)
    {
        static unsigned __int64 _OptionsStorage;
        return &_OptionsStorage;
    }
#endif

#if defined _M_CEE && !defined _M_CEE_PURE
    #pragma managed(pop)
#endif

#define _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS (*__local_stdio_printf_options())
#define _CRT_INTERNAL_LOCAL_SCANF_OPTIONS  (*__local_stdio_scanf_options ())



#define _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION (1ULL << 0)
#define _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR       (1ULL << 1)
#define _CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS           (1ULL << 2)
#define _CRT_INTERNAL_PRINTF_LEGACY_MSVCRT_COMPATIBILITY      (1ULL << 3)
#define _CRT_INTERNAL_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS     (1ULL << 4)
#define _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING                (1ULL << 5)


#define _CRT_INTERNAL_SCANF_SECURECRT                   (1ULL << 0)
#define _CRT_INTERNAL_SCANF_LEGACY_WIDE_SPECIFIERS      (1ULL << 1)
#define _CRT_INTERNAL_SCANF_LEGACY_MSVCRT_COMPATIBILITY (1ULL << 2)
// CRT headers are included into some kinds of source files where only data type
// definitions and macro definitions are required but function declarations and
// inline function definitions are not.  These files include assembly files, IDL
// files, and resource files.  The tools that process these files often have a
// limited ability to process C and C++ code.  The _CRT_FUNCTIONS_REQUIRED macro
// is defined to 1 when we are compiling a file that actually needs functions to
// be declared (and defined, where applicable), and to 0 when we are compiling a
// file that does not.  This allows us to suppress declarations and definitions
// that are not compilable with the aforementioned tools.
#if !defined _CRT_FUNCTIONS_REQUIRED
    #if defined __assembler || defined __midl || defined RC_INVOKED
        #define _CRT_FUNCTIONS_REQUIRED 0
    #else
        #define _CRT_FUNCTIONS_REQUIRED 1
    #endif
#endif
#70
Tips & tricks / Re: Silly test for msvcrt and ...
Last post by jack - February 08, 2026, 12:52:41 PM
@TimoVJL I am back early
trying to link against ucrt with Pelles C is not straightforward but it easy using llvm-mingw gcc from https://github.com/mstorsjo/llvm-mingw/releases
using the 64-bit version I compiled the following code: gcc sprintf-timing.c -o sprintf-timing
sprintf-timing.c
#include <stdio.h>
#include <windows.h>

#define ITERATIONS 1000000

int main() {
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
    char buffer[256];
    LARGE_INTEGER frequency, start, end;
    double x=1.2345678901234567890;
    double total_time = 0;
   
    QueryPerformanceFrequency(&frequency);
   
    for (int i = 0; i < ITERATIONS; i++) {
        QueryPerformanceCounter(&start);
       
        sprintf(buffer, "%.15g", x);
       
        QueryPerformanceCounter(&end);
       
        total_time += (double)(end.QuadPart - start.QuadPart) / frequency.QuadPart;
    }
   
    printf("Average sprintf time: %.2f nanoseconds\n",
           (total_time / ITERATIONS) * 1e9);
}
as you mentioned to Vortex, ucrtbase does not provide a straight printf or sprintf but it does provide stdio_common_vfprintf and stdio_common_vsprintf
I ran the following from the msys2 shell
objdump.exe -d -M intel,x86-64 sprintf-timing.exe >sprintf-timing.txt
and then searched the disassembly for stdio_common_vsprintf, here are the relevant pieces
0000000140001f30 <printf>:
   140001f30: 56                    push   rsi
   140001f31: 57                    push   rdi
   140001f32: 48 83 ec 38          sub    rsp,0x38
   140001f36: 48 89 ce              mov    rsi,rcx
   140001f39: 48 89 54 24 58        mov    QWORD PTR [rsp+0x58],rdx
   140001f3e: 4c 89 44 24 60        mov    QWORD PTR [rsp+0x60],r8
   140001f43: 4c 89 4c 24 68        mov    QWORD PTR [rsp+0x68],r9
   140001f48: 48 8d 44 24 58        lea    rax,[rsp+0x58]
   140001f4d: 48 89 44 24 30        mov    QWORD PTR [rsp+0x30],rax
   140001f52: e8 99 07 00 00        call   1400026f0 <__local_stdio_printf_options>
   140001f57: 48 8b 38              mov    rdi,QWORD PTR [rax]
   140001f5a: b9 01 00 00 00        mov    ecx,0x1
   140001f5f: e8 ac 07 00 00        call   140002710 <__acrt_iob_func>
   140001f64: 48 8b 4c 24 30        mov    rcx,QWORD PTR [rsp+0x30]
   140001f69: 48 89 4c 24 20        mov    QWORD PTR [rsp+0x20],rcx
   140001f6e: 48 89 f9              mov    rcx,rdi
   140001f71: 48 89 c2              mov    rdx,rax
   140001f74: 49 89 f0              mov    r8,rsi
   140001f77: 45 31 c9              xor    r9d,r9d
   140001f7a: e8 c1 09 00 00        call   140002940 <__stdio_common_vfprintf>
   140001f7f: 90                    nop
   140001f80: 48 83 c4 38          add    rsp,0x38
   140001f84: 5f                    pop    rdi
   140001f85: 5e                    pop    rsi
   140001f86: c3                    ret
   140001f87: cc                    int3
   140001f88: cc                    int3
   140001f89: cc                    int3
   140001f8a: cc                    int3
   140001f8b: cc                    int3
   140001f8c: cc                    int3
   140001f8d: cc                    int3
   140001f8e: cc                    int3
   140001f8f: cc                    int3

0000000140001f90 <sprintf>:
   140001f90: 56                    push   rsi
   140001f91: 57                    push   rdi
   140001f92: 48 83 ec 38          sub    rsp,0x38
   140001f96: 48 89 d6              mov    rsi,rdx
   140001f99: 48 89 cf              mov    rdi,rcx
   140001f9c: 4c 89 44 24 60        mov    QWORD PTR [rsp+0x60],r8
   140001fa1: 4c 89 4c 24 68        mov    QWORD PTR [rsp+0x68],r9
   140001fa6: 48 8d 44 24 60        lea    rax,[rsp+0x60]
   140001fab: 48 89 44 24 30        mov    QWORD PTR [rsp+0x30],rax
   140001fb0: e8 3b 07 00 00        call   1400026f0 <__local_stdio_printf_options>
   140001fb5: 48 8b 08              mov    rcx,QWORD PTR [rax]
   140001fb8: 48 83 c9 02          or     rcx,0x2
   140001fbc: 48 8b 44 24 30        mov    rax,QWORD PTR [rsp+0x30]
   140001fc1: 48 89 44 24 28        mov    QWORD PTR [rsp+0x28],rax
   140001fc6: 48 c7 44 24 20 00 00 mov    QWORD PTR [rsp+0x20],0x0
   140001fcd: 00 00
   140001fcf: 48 89 fa              mov    rdx,rdi
   140001fd2: 49 c7 c0 ff ff ff ff mov    r8,0xffffffffffffffff
   140001fd9: 49 89 f1              mov    r9,rsi
   140001fdc: e8 6f 09 00 00        call   140002950 <__stdio_common_vsprintf>
   140001fe1: 90                    nop
   140001fe2: 48 83 c4 38          add    rsp,0x38
   140001fe6: 5f                    pop    rdi
   140001fe7: 5e                    pop    rsi
   140001fe8: c3                    ret
   140001fe9: cc                    int3
   140001fea: cc                    int3
   140001feb: cc                    int3
   140001fec: cc                    int3
   140001fed: cc                    int3
   140001fee: cc                    int3
   140001fef: cc                    int3

00000001400026f0 <__local_stdio_printf_options>:
   1400026f0: 48 8d 05 51 29 00 00 lea    rax,[rip+0x2951]        # 140005048 <options>
   1400026f7: c3                    ret
   1400026f8: cc                    int3
   1400026f9: cc                    int3
   1400026fa: cc                    int3
   1400026fb: cc                    int3
   1400026fc: cc                    int3
   1400026fd: cc                    int3
   1400026fe: cc                    int3
   1400026ff: cc                    int3

the only missing piece of the puzzle is 140005048 <options>