Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Minimalist Runtime Library for Microsoft® C Compiler

Purpose
Prerequisites
Preparation
Usage
Dependency
Restriction
Limitations
Workaround
Implementation
Startup Routines
Stack Allocation and Runtime Checks
Signed 64-bit Integer Arithmetic for 32-bit Execution Environment
Unsigned 64-bit Integer Arithmetic for 32-bit Execution Environment
64-bit Integer Arithmetic
128-bit Integer Arithmetic for 32-bit Execution Environment
128-bit Integer Arithmetic
128-bit Integer Shift and Rotation
Floating-Point Functions
Floating-Point to ASCII Character String Conversion
ASCII Character String to Floating-Point Conversion
Unicode Character String to Floating-Point Conversion
Integer to ASCII Character String Conversion
Integer to Unicode Character String Conversion
ASCII Character String to Integer Conversion
Unicode Character String to Integer Conversion
ASCII Character String Handling
Unicode Character String Handling
ASCII Character Classification
Unicode Character Classification
Text Output
Buffer Manipulation
Endian Conversion
Miscellaneous Functions
POSIX Functions
Random Number Generators
Download
Authenticity and Integrity

Purpose

Build a minimalist Win32 runtime library to create small(er) and fast(er) pure Win32 applications, command line alias console programs and DLLs with Microsoft’s Visual C compilers, without the (bloat, bugs and overhead of the) MSVCRT runtime libraries, using only functions of the Win32 API, for use on Windows® XP and newer versions of Windows NT as well as Windows PE.

The minimalist Win32 runtime library provides the compiler helper routines, internal functions and intrinsics called from objects created with Microsoft’s Visual C compiler, the startup routines called from Windows’ module loader, plus various basic as well as extraneous runtime functions.

Note: the minimalist Win32 runtime library is not (intended to be) a C standard runtime library, it offers (almost) no ANSI C, ISO C or POSIX functions like longjmp(), qsort(), scanf(), setjmp() or strerror(), no objects like FILE and functions like ferror() which operate on them, and no global variables like errno or stderr, but functions which replace cprintf(), fputchar(), printf(), putch(), puts(), putw() etc.

The MSKB article 99456 lists some equivalent functions of the Win32 API.

Prerequisites

A platform or Windows SDK for Windows XP and newer versions of Windows NT.
See the MSDN article Prepare Your Development Environment for context.

Preparation

Perform the following 8 (optionally 9) steps to build the minimalist Win32 runtime library from the sources and verify the build.
  1. Download the makefile NOMSVCRT.MAK into an arbitrary, preferable empty directory.

    Note: the makefile contains the sources as inline files.

  2. Run the following command line to build the object library NOMSVCRT.LIB for the I386 alias x86 processor architecture:

    NMAKE.EXE /R /F NOMSVCRT.MAK
    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.
    Microsoft (R) Program Maintenance Utility Version 10.00.40219.01
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    	ML.EXE /c /coff /FoALLOCA.OBJ /nologo /safeseh /TanmFC87.tmp /W3 /X
     Assembling: nmFC87.tmp
    …
    	ML.EXE /c /coff /DJMPLESS /FoUDIV128.OBJ /nologo /safeseh /TanmFC9B.tmp /W3 /X
     Assembling: nmFC9B.tmp
    …
    	CL.EXE /c /DSPECIAL /FoFLTUSED.OBJ /fp:precise /GA /Gd /GF /Gy /nologo /O2 /QIfist /TcnmFCA1.tmp /W4 /wd4201 /wd4204 /wd4214 /Zl
    cl : Command line warning D9035 : option 'QIfist' has been deprecated and will be removed in a future release
    nmFCA1.tmp
    nmfca1.tmp(2027) : warning C4057: 'function' : 'unsigned int *' differs in indirection to slightly different base types from 'int *'
    nmfca1.tmp(2576) : warning C4244: '=' : conversion from '__int64' to 'double', possible loss of data
    nmfca1.tmp(2612) : warning C4244: '=' : conversion from 'unsigned __int64' to 'double', possible loss of data
    nmfca1.tmp(2972) : warning C4244: '=' : conversion from '__int64' to 'double', possible loss of data
    nmfca1.tmp(3008) : warning C4244: '=' : conversion from 'unsigned __int64' to 'double', possible loss of data
    …
    	ML.EXE /c /coff /DJONES /FoCNTR64.OBJ /nologo /safeseh /TanmFCD5.tmp /W3 /X
     Assembling: nmFCD5.tmp
    …
    	ML.EXE /c /coff /DINTERLEAVE /FoMSQR32.OBJ /nologo /safeseh /TanmFCD8.tmp /W3 /X
     Assembling: nmFCD8.tmp
    …
    	ML.EXE /c /coff /FoWMEMSWAP.OBJ /nologo /safeseh /TanmFD09.tmp /W3 /X
     Assembling: nmFD09.tmp
    	CL.EXE /c /FoDLLMAIN.OBJ /GA /GF /Gy /nologo /O1 /Os /TcnmFD0A.tmp /W4 /wd4100 /we4013 /Zl
    nmFD0A.tmp
    	CL.EXE /c /FoWINMAIN.OBJ /GA /GF /Gy /nologo /O1 /Os /TcnmFD0B.tmp /W4 /wd4090 /wd4100 /wd4189 /we4013 /Zl
    nmFD0B.tmp
    	CL.EXE /c /FoWWINMAIN.OBJ /GA /GF /Gy /nologo /O1 /Os /TcnmFD0C.tmp /W4 /wd4090 /wd4100 /wd4189 /we4013 /Zl
    nmFD0C.tmp
    	CL.EXE /c /DKEYPRESS /FoWMAIN.OBJ /GA /GF /Gy /nologo /O1 /Oi /Os /TcnmFD0D.tmp /W4 /wd4090 /wd4100 /wd4201 /we4013 /Zl
    nmFD0D.tmp
    nmFD0D.tmp(360) : warning C4996: 'wcscpy': This function or variable may be unsafe. Consider using wcscpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
    	CL.EXE /c /DKEYPRESS /FoMAIN.OBJ /GA /GF /Gy /nologo /O1 /Oi /Os /TcnmFD0E.tmp /W4 /wd4090 /wd4100 /wd4201 /we4013 /Zl
    nmFD0E.tmp
    nmFD0E.tmp(333) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
    	CL.EXE /c /FoNOMSVCRT.OBJ /GA /GF /Gy /nologo /O1 /Os /TcnmFD0F.tmp /W4 /wd4047 /wd4201 /we4013 /Zl
    nmFD0F.tmp
    	LINK.EXE /LIB /MACHINE:X86 /NODEFAULTLIB /NOLOGO /OUT:NOMSVCRT.LIB ALLOCA.OBJ ALLOCA4.OBJ ALLOCA8.OBJ ALLOCA16.OBJ ALLABS.OBJ ALLDIV.OBJ ALLDVRM.OBJ ALLMUL.OBJ ALLNEG.OBJ ALLREM.OBJ ALLROL.OBJ ALLROR.OBJ ALLSHL.OBJ ALLSHR.OBJ AULLDIV.OBJ AULLDVRM.OBJ AULLREM.OBJ AULLSHR.OBJ MUL128.OBJ MULH.OBJ UDIV128.OBJ UMUL128.OBJ UMULH.OBJ CIACOS.OBJ CIASIN.OBJ CIATAN.OBJ CIATAN2.OBJ CICOS.OBJ CICOSH.OBJ CIEXP.OBJ CIFMOD.OBJ CILOG.OBJ CILOG10.OBJ CIPOW.OBJ CISIN.OBJ CISINH.OBJ CISQRT.OBJ CITAN.OBJ CITANH.OBJ FABS.OBJ FCEIL.OBJ FCOPYSIGN.OBJ FDIM.OBJ FFLOOR.OBJ FFREXP.OBJ FHYPOT.OBJ FLDEXP.OBJ FLOGB.OBJ FMAX.OBJ FMIN.OBJ FPOWN.OBJ FRAND.OBJ FREMAINDER.OBJ FREMQUO.OBJ FRINT.OBJ FROUND.OBJ FSIGNBIT.OBJ FTRUNC.OBJ FACOSH.OBJ FACOT.OBJ FACOT2.OBJ FACOTH.OBJ FASINH.OBJ FATANH.OBJ FCOT.OBJ FCOTH.OBJ FEXP2.OBJ FEXP10.OBJ FEXPM1.OBJ FLOG.OBJ FLOG1P.OBJ FLOG2.OBJ FLOG10.OBJ FLTUSED.OBJ FTOL.OBJ FTOL2.OBJ FTOL2SSE.OBJ MODF.OBJ ILOGB.OBJ SWAB.OBJ HTONLL.OBJ HTONL.OBJ HTONS.OBJ LABS.OBJ LMAX.OBJ LMIN.OBJ LSGN.OBJ LZCNT32.OBJ LZCNT64.OBJ TZCNT32.OBJ TZCNT64.OBJ CNTR32.OBJ CNTR64.OBJ LFSR32.OBJ LFSR64.OBJ LFSR128.OBJ MSQR32.OBJ MSQR64.OBJ MWCG32.OBJ MWCG64.OBJ REV8.OBJ REV16.OBJ REV32.OBJ REV64.OBJ LMEMCHR.OBJ LMEMCMP.OBJ LMEMCPY.OBJ LMEMMOVE.OBJ LMEMSET.OBJ LMEMSWAP.OBJ MEMCHR.OBJ MEMCMP.OBJ MEMCPY.OBJ MEMMOVE.OBJ MEMSET.OBJ MEMSWAP.OBJ STRCAT.OBJ STRCHR.OBJ STRCMP.OBJ STRCPY.OBJ STRLEN.OBJ STRNCAT.OBJ STRNCMP.OBJ STRNSET.OBJ STRRCHR.OBJ STRREV.OBJ STRSET.OBJ STRSTR.OBJ WCSCAT.OBJ WCSCHR.OBJ WCSCMP.OBJ WCSCPY.OBJ WCSLEN.OBJ WCSNCAT.OBJ WCSNCMP.OBJ WCSNSET.OBJ WCSRCHR.OBJ WCSREV.OBJ WCSSET.OBJ WCSSTR.OBJ WMEMCHR.OBJ WMEMCMP.OBJ WMEMCPY.OBJ WMEMMOVE.OBJ WMEMSET.OBJ WMEMSWAP.OBJ DLLMAIN.OBJ WINMAIN.OBJ WWINMAIN.OBJ WMAIN.OBJ MAIN.OBJ NOMSVCRT.OBJ
    FLOG.OBJ : warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
    FEXP10.OBJ : warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
    FEXP2.OBJ : warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
    Note: a makefile which builds the object library NOMSVCRT.LIB for the AMD64 alias x64 processor architecture is available upon request.
  3. Download the header file NOMSVCRT.H and the ANSI C source file NOMSVCRT.C into the directory used in steps 1. and 2.

  4. Run the following command lines to build the sample GUI alias Windows application NOMSVCRT.EXE, the sample DLL NOMSVCRT.DLL and the sample CUI or CLI alias console program NOMSVCRT.COM:

    SET CL=/GA /GF /Gy /O1 /Os /Oy- /W4 /Zl
    SET LINK=/DYNAMICBASE /FIXED:NO /LARGEADDRESSAWARE /NXCOMPAT /OPT:REF /OSVERSION:5.1 /RELEASE
    CL.EXE NOMSVCRT.C
    CL.EXE /DUNICODE NOMSVCRT.C
    CL.EXE /DDLL /LD NOMSVCRT.C
    CL.EXE /DCONSOLE /FeNOMSVCRT.COM NOMSVCRT.C
    CL.EXE /DCONSOLE /DUNICODE /FeNOMSVCRT.COM NOMSVCRT.C
    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NOMSVCRT.C
    NOMSVCRT.C(288) : warning C4100: 'nCmdShow' : unreferenced formal parameter
    NOMSVCRT.C(286) : warning C4100: 'hPrevInstance' : unreferenced formal parameter
    NOMSVCRT.C(285) : warning C4100: 'hInstance' : unreferenced formal parameter
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DYNAMICBASE /FIXED:NO /LARGEADDRESSAWARE /NXCOMPAT /OPT:REF /OSVERSION:5.1 /RELEASE
    /out:NOMSVCRT.exe
    NOMSVCRT.obj
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NOMSVCRT.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DYNAMICBASE /FIXED:NO /LARGEADDRESSAWARE /NXCOMPAT /OPT:REF /OSVERSION:5.1 /RELEASE
    /out:NOMSVCRT.exe
    NOMSVCRT.obj
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NOMSVCRT.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DYNAMICBASE /FIXED:NO /LARGEADDRESSAWARE /NXCOMPAT /OPT:REF /OSVERSION:5.1 /RELEASE
    /out:NOMSVCRT.dll
    /dll
    /implib:NOMSVCRT.lib
    NOMSVCRT.obj
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NOMSVCRT.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DYNAMICBASE /FIXED:NO /LARGEADDRESSAWARE /NXCOMPAT /OPT:REF /OSVERSION:5.1 /RELEASE
    /out:NOMSVCRT.COM
    NOMSVCRT.obj
    
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    NOMSVCRT.C
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /DYNAMICBASE /FIXED:NO /LARGEADDRESSAWARE /NXCOMPAT /OPT:REF /OSVERSION:5.1 /RELEASE
    /out:NOMSVCRT.COM
    NOMSVCRT.obj
    Each resulting portable executable file is just 4 kB to 7 kB small.

    Note: the downloadable sample portable executable files are a bit larger, they result from the optional step 8.

  5. [Screenshot of NOMSVCRT.EXE] Start the sample application NOMSVCRT.EXE built in step 4., either per double-click or on the command line, optionally with arbitrary arguments: it displays a message box like that shown on the right.

  6. Run one of the following command lines to load the sample DLL NOMSVCRT.DLL built in step 4.:

    MSIEXEC.EXE /Y "%CD%\NOMSVCRT.DLL"
    REGSVR32.EXE "%CD%\NOMSVCRT.DLL"
    RUNDLL32.EXE "%CD%\NOMSVCRT.DLL",#0
    RUNDLL32.EXE "%CD%\NOMSVCRT.DLL",foobar
    Note: on 64-bit editions of Windows, the execution environments of NOMSVCRT.DLL and MSIExec.exe must match!

    Windows’ module loader executes the DLL’s startup routine, which displays two message boxes like those shown below:

    [Screenshot of NOMSVCRT.DLL run via RUNDLL32.EXE] [Screenshot of NOMSVCRT.DLL run via RUNDLL32.EXE]

    Note: the error message boxes displayed from RegSvr32.exe and RunDLL32.exe are expected: NOMSVCRT.DLL does neither implement any of the functions DllInstall(), DllRegisterServer() and DllUnregisterServer() called from the Regsvr32 tool, nor the Rundll32 Interface.

  7. Run the following command line to execute the console program NOMSVCRT.COM built in step 4.:

    NOMSVCRT.COM foo\"bar\\baz
    It prints output like the following text:
    argc:		2
    argv[0]:	0x0046FB3C	NOMSVCRT.COM
    argv[1]:	0x0046FB58	foo"bar\\baz
    
    envp[0]:	0x008B0B18	ALLUSERSPROFILE=C:\ProgramData
    envp[1]:	0x008B0B56	APPDATA=C:\Users\Stefan\AppData\Roaming
    envp[2]:	0x008B0BA6	CommonProgramFiles=C:\Program Files (x86)\Common Files
    envp[3]:	0x008B0C14	CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
    envp[4]:	0x008B0C8C	CommonProgramW6432=C:\Program Files\Common Files
    envp[5]:	0x008B0CEE	COMPUTERNAME=AMNESIAC
    envp[6]:	0x008B0D1A	ComSpec=C:\Windows\system32\cmd.exe
    envp[7]:	0x008B0D62	COPYCMD=/V /Z
    envp[8]:	0x008B0D7E	DevMgr_Show_Details=*
    envp[9]:	0x008B0DAA	DevMgr_Show_NonPresent_Devices=*
    envp[10]:	0x008B0DEC	DIRCMD=/A /P /X
    envp[11]:	0x008B0E0C	FP_NO_HOST_CHECK=NO
    envp[12]:	0x008B0E34	HOMEDRIVE=C:
    envp[13]:	0x008B0E4E	HOMEPATH=\Users\Stefan
    envp[14]:	0x008B0E7C	LOCALAPPDATA=C:\Users\Stefan\AppData\Local
    envp[15]:	0x008B0ED2	LOGONSERVER=\\AMNESIAC
    envp[16]:	0x008B0F00	NUMBER_OF_PROCESSORS=2
    envp[17]:	0x008B0F2E	OS=Windows_NT
    envp[18]:	0x008B0F4A	Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\Commands;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Program Files\Microsoft SDKs\Windows\v7.0\bin
    envp[19]:	0x008B10A4	PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
    envp[20]:	0x008B1120	PROCESSOR_ARCHITECTURE=x86
    envp[21]:	0x008B1156	PROCESSOR_ARCHITEW6432=AMD64
    envp[22]:	0x008B1190	PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 23 Stepping 10, GenuineIntel
    envp[23]:	0x008B1222	PROCESSOR_LEVEL=6
    envp[24]:	0x008B1246	PROCESSOR_REVISION=170a
    envp[25]:	0x008B1276	ProgramData=C:\ProgramData
    envp[26]:	0x008B12AC	ProgramFiles=C:\Program Files (x86)
    envp[27]:	0x008B12F4	ProgramFiles(x86)=C:\Program Files (x86)
    envp[28]:	0x008B1346	ProgramW6432=C:\Program Files
    envp[29]:	0x008B1382	PROMPT=$P$G
    envp[30]:	0x008B139A	PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
    envp[31]:	0x008B141C	PUBLIC=C:\Users\Public
    envp[32]:	0x008B144A	SystemDrive=C:
    envp[33]:	0x008B1468	SystemRoot=C:\Windows
    envp[34]:	0x008B1494	TEMP=C:\Users\Stefan\AppData\Local\Temp
    envp[35]:	0x008B14E4	TMP=C:\Users\Stefan\AppData\Local\Temp
    envp[36]:	0x008B1532	USERDOMAIN=AMNESIAC
    envp[37]:	0x008B155A	USERDOMAIN_ROAMINGPROFILE=AMNESIAC
    envp[38]:	0x008B15A0	USERNAME=Stefan
    envp[39]:	0x008B15C0	USERPROFILE=C:\Users\Stefan
    envp[40]:	0x008B15F8	windir=C:\Windows
    Note: when started in its own console window, for example per double-click, NOMSVCRT.COM waits for a keypress before it exits and its console window closes; it beeps once and flashes the title bar of its console window to indicate this wait state.
  8. Optionally download the icon file NOMSVCRT.ICO into the directory used in steps 1. to 3., then run the following command line to build the three sample executable files with (almost) all bells and whistles, i.e. including a resource containing the icon, an application manifest and version information, plus a custom DOS stub, and digitally sign them with your own X.509 certificate:

    NMAKE.EXE /R /F NOMSVCRT.MAK samples sign
    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.
    Microsoft (R) Program Maintenance Utility Version 10.00.40219.01
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    	CERTUTIL.EXE /DecodeHex /F /V nm34A.tmp NOMSVCRT.DOS
    Input Length = 730
    Output Length = 160
    CertUtil: -decodehex command completed successfully.
    	RC.EXE /DUNICODE /FoNOMSVCRT.RES /L 0 /N /R /V nm34B.tmp
    Microsoft (R) Windows (R) Resource Compiler Version 6.1.7600.16385
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    Using codepage 1252 as default
    Creating NOMSVCRT.RES
    C:\Program Files\Microsoft Visual Studio 10.0\Include\string.h(54) : warning RC4011: identifier truncated to '_CRT_SECURE_CPP_OVERLOAD_STANDA'
    C:\Program Files\Microsoft Visual Studio 10.0\Include\string.h(76) : warning RC4011: identifier truncated to '_CRT_SECURE_CPP_OVERLOAD_SECURE'
    
    nm34B.tmp.
    Writing ICON:1, lang:0x0,       size 9640
    Writing ICON:2, lang:0x0,       size 4264
    Writing ICON:3, lang:0x0,       size 1128
    Writing GROUP_ICON:1,   lang:0x0,       size 48.
    Writing 24:1,   lang:0x0,       size 1305.
    Writing VERSION:1,      lang:0x0,       size 1188
    	CVTRES.EXE /MACHINE:X86 /NOLOGO /OUT:NOMSVCRT.CVT /READONLY NOMSVCRT.RES
    	CL.EXE /c /DUNICODE /FoNOMSVCRT.TMP /GA /GF /Gy /I. /nologo /O1 /Os /TcNOMSVCRT.C /W4 /we4013 /Zl
    NOMSVCRT.C
    	LINK.EXE /LINK /DEFAULTLIB:NOMSVCRT.LIB /DYNAMICBASE /ENTRY:wWinMainCRTStartup /FIXED:NO /LARGEADDRESSAWARE /MACHINE:X86 /NOLOGO /NXCOMPAT/OPT:REF /OSVERSION:5.1 /OUT:NOMSVCRT.EXE /RELEASE /SAFESEH /STUB:NOMSVCRT.DOS /SUBSYSTEM:WINDOWS,5.1 /SWAPRUN:CD,NET /TEST /VERSION:0.815 NOMSVCRT.TMP NOMSVCRT.CVT
    LINK : file alignment: 512, section alignment: 4096
    LINK : section '.sdata' (C0000040) merged into '.data' (C0000040)
    LINK : section '.xdata' (40000040) merged into '.rdata' (40000040)
    	Erase NOMSVCRT.TMP
    	CL.EXE /c /DDLL /FoNOMSVCRT.TMP /GA /GF /Gy /I. /nologo /O1 /Os /TcNOMSVCRT.C /W4 /we4013 /Zl
    NOMSVCRT.C
    	LINK.EXE /LINK /DEFAULTLIB:NOMSVCRT.LIB /DLL /DYNAMICBASE /ENTRY:_DllMainCRTStartup@12 /FIXED:NO /LARGEADDRESSAWARE /MACHINE:X86 /NOLOGO /NXCOMPAT /OPT:REF /OSVERSION:5.1 /OUT:NOMSVCRT.DLL /RELEASE /SAFESEH /STUB:NOMSVCRT.DOS /SUBSYSTEM:WINDOWS,5.1 /SWAPRUN:CD,NET /TEST /VERSION:0.815 NOMSVCRT.TMP NOMSVCRT.CVT
    LINK : file alignment: 512, section alignment: 4096
    LINK : section '.sdata' (C0000040) merged into '.data' (C0000040)
    LINK : section '.xdata' (40000040) merged into '.rdata' (40000040)
    	Erase NOMSVCRT.TMP
    	CL.EXE /c /DCONSOLE /DUNICODE /FoNOMSVCRT.TMP /GA /GF /Gy /I. /nologo /O1 /Os /TcNOMSVCRT.C /W4 /we4013 /Zl
    NOMSVCRT.C
    	LINK.EXE /LINK /DEFAULTLIB:NOMSVCRT.LIB /DYNAMICBASE /ENTRY:wmainCRTStartup /FIXED:NO /LARGEADDRESSAWARE /MACHINE:X86 /NOLOGO /NXCOMPAT /OPT:REF /OSVERSION:5.1 /OUT:NOMSVCRT.COM /RELEASE /SAFESEH /STUB:NOMSVCRT.DOS /SUBSYSTEM:CONSOLE,5.1 /SWAPRUN:CD,NET /TEST /VERSION:0.815 NOMSVCRT.TMP NOMSVCRT.CVT
    LINK : file alignment: 512, section alignment: 4096
    LINK : section '.sdata' (C0000040) merged into '.data' (C0000040)
    LINK : section '.xdata' (40000040) merged into '.rdata' (40000040)
    	Erase NOMSVCRT.TMP
    	".\NOMSVCRT.EXE" foobar "foobaz" "foo\\bar" foo\\" "baz foo\\\"bar \\"foo baz"
    	RUNDLL32.EXE ".\NOMSVCRT.DLL",foobar
    	".\NOMSVCRT.COM" foobar "foobaz" "foo\\bar" foo\\" "baz foo\\\"bar \\"foo baz"
    	SIGNTOOL.EXE Sign /A /D "NOMSVCRT Sample Application, Console Program or DLL" /DU https://skanthak.homepage.t-online.de/nomsvcrt.html /T http://timestamp.verisign.com/scripts/timstamp.dll /V NOMSVCRT.EXE NOMSVCRT.DLL NOMSVCRT.COM
    The following certificate was selected:
        Issued to: Stefan Kanthak
        Issued by: eSKamation Certification Authority
        Expires:   Thu Feb 22 22:27:43 2052
        SHA1 hash: 1459BCFF425225185367AE33591DA1A84ECBA07C
    
    
    Attempting to sign: NOMSVCRT.EXE NOMSVCRT.DLL NOMSVCRT.COM
    Successfully signed and timestamped: NOMSVCRT.EXE NOMSVCRT.DLL NOMSVCRT.COM
    
    Number of files successfully Signed: 3
    Number of warnings: 0
    Number of errors: 0
  9. Finally move the header file NOMSVCRT.H downloaded in step 3. into one of the include directories used by the Visual C compiler, and the object library NOMSVCRT.LIB built in step 2. into one of the lib directories for the I386 alias x86 appropriate processor architecture.

Usage

// Copyright © 2004-2020, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>

// Minimalist Win32 Runtime Library for Microsoft C Compiler 20xy

#define NOMINMAX
#define STRICT
#define WIN32_LEAN_AND_MEAN

#define WINVER		0x0500
#define _WIN32_WINNT	0x0500

#include <windows.h>
…
#define IEEE_754	// for floating-point routines
#define INTRINSIC	// for intrinsics
#include <nomsvcrt.h>
…
#ifdef DLL
// see <https://msdn.microsoft.com/en-us/library/ms682583.aspx>
// and <https://msdn.microsoft.com/en-us/library/ms682596.aspx>

BOOL	WINAPI	DllMain(HANDLE hModule,
		        DWORD  dwReason,
		        LPVOID lpReserved)
{
	…
	return TRUE;
}
#else // DLL
#ifdef CONSOLE
#ifdef UNICODE
// see <https://msdn.microsoft.com/en-us/library/6wd819wh.aspx>
// and <https://msdn.microsoft.com/en-us/library/bky3b5dh.aspx>

int	wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
	return PrintString(STDOUT, L"Hello world!\n");
}
#else // ANSI
// see <https://msdn.microsoft.com/en-us/library/3ze4ytsc.aspx>
// and <https://msdn.microsoft.com/en-us/library/6wd819wh.aspx>

int	main(int argc, char *argv[], char *envp[])
{
	return PrintString(STDOUT, "Hello world!\n");
}
#endif // UNICODE
#else // WINDOWS
#ifdef UNICODE
// see <https://msdn.microsoft.com/en-us/library/ms633559.aspx>
// and <https://msdn.microsoft.com/en-us/library/ff381406.aspx>

INT	WINAPI	wWinMain(HINSTANCE hInstance,
		         HINSTANCE hPrevInstance,
		         LPWSTR    lpCmdLine,
		         INT       nCmdShow)
{
	// see <https://msdn.microsoft.com/en-us/library/ms645507.aspx>

	return MessageBoxEx(HWND_DESKTOP, L"Hello world!\n", L"NOMSVCRT", MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
}
#else // ANSI
// see <https://msdn.microsoft.com/en-us/library/ms633559.aspx>
// and <https://msdn.microsoft.com/en-us/library/ff381406.aspx>

INT	WINAPI	WinMain(HINSTANCE hInstance,
		        HINSTANCE hPrevInstance,
		        LPSTR     lpCmdLine,
		        INT       nCmdShow)
{
	// see <https://msdn.microsoft.com/en-us/library/ms645507.aspx>

	return MessageBoxEx(HWND_DESKTOP, "Hello world!\n", "NOMSVCRT", MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
}
#endif // UNICODE
#endif // CONSOLE
#endif // DLL
CL.EXE /GA /GF /Gy /Oi /Zl … ‹source›.c
Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

Dependency

WINDOWS.H must be included before NOMSVCRT.H.

Note: the functions max() and min() are defined only when the corresponding preprocessor macros max and min are not defined; to disable their definition, define the preprocessor macro NOMINMAX before you include WINDOWS.H.

Restriction

The functions PrintBuffer(), PrintChar() and PrintFormat(), which replace POSIX functions like fputchar(), printf(), putch(), puts(), putw() etc., write ASCII in ANSI console programs and UTF-16LE in Unicode console programs to their (redirected) standard output and standard error.

Note: use the format specifiers %hc and %hs to print ASCII characters and character strings from Unicode console programs, and the format specifiers %lc alias %wc and %ls alias %ws to print UTF-16LE characters and character strings from ANSI console programs.

Note: in order to prevent a mix of ASCII and UTF-16LE which may be rendered as mojibake, in ANSI console programs the Unicode functions PrintBufferW(), PrintCharW() and PrintFormatW(), and in Unicode console programs the ANSI functions PrintBufferA(), PrintCharA() and PrintFormatA(), write nothing when their output is redirected to a file, but return FALSE and yield Win32 error 1288 alias ERROR_INVALID_CRUNTIME_PARAMETER instead.

Limitations

The header file NOMSVCRT.H and the object library NOMSVCRT.LIB have the following limitations:

Workaround

The following kludge prints IEEE754 double-precision floating-point numbers (almost) like the %a, %A, %g and %G conversion specifiers:
// Copyright © 2004-2020, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>

// Minimalist Win32 Runtime Library for Microsoft C Compiler 20xy

#include <windows.h>
#include <nomsvcrt.h>

int	kludge(char *string, double number)
{
	// see <https://msdn.microsoft.com/en-us/library/0b34tf65.aspx>

	union	_real8
	{
		// float64 = (-1)**sign * significand * 2**(exponent - 1023)
		//
		// 53-bit significand is 0.fraction if 0 = exponent,
		//                       1.fraction if 0 < exponent < 2047,
		//                       1.*        if     exponent = 2047

		double	float64;
		struct	_IEEE_754_DOUBLE_PRECISION
		{
			unsigned long long	fraction : 52;
			unsigned long long	exponent : 11;
			unsigned long long	sign     : 1;
		};
	} real8 = {number};

	char	decimal[25];

	dtostr(number, decimal);

	return PrintFormat(STDOUT, "%s = %c0x%c.%013I64Xp%d\t= %s\n",
	                   string,
	                   real8.sign ? '-' : '+', real8.exponent ? '1' : '0', real8.fraction, real8.exponent ? (int) real8.exponent - 1023 : 1 - 1023,
	                   decimal);
}

#define BIG		(1.0e308)
#define INFINITY	(1.0e308 + 1.0e308)

const	double	between    = -4503599627370495.5;				// = 2**52 - 1 / 2
const	double	big        = BIG;
const	double	denormal   = -4.940656458412465441765687928682213724e-324;	// = 2**-1074
const	double	e          = +2.718281828459045235360287471352662498;
const	double	epsilon    = -2.220446049250313080847263336181640625e-16;	// = 2**-52
const	double	indefinite = INFINITY * 0.0;
const	double	infinity   = INFINITY;
const	double	maximum    = +1.797693134862315708145274237317043568e+308;	// = 2**+1024 * (1 - 2**-53)
const	double	minimum    = -2.225073858507201383090232717332404064e-308;	// = 2**-1022
const	double	null       = BIG / INFINITY;
const	double	omicron    = +9.999999999999998889776975374843459576e-1;	// = 1 - 2**-53
const	double	pi         = +3.141592653589793238462643383279502884;
const	double	ypsilon    = +4503599627370496.0;				// = 2**52
const	double	zero       = -0.0;

int	main(void)
{
	double	eps;
	double	max;
	double	min;
	double	nan        = zero / zero;
	double	yps;
	double	overflow   = 1.0;
	double	underflow  = 1.0;

	do {	// compute 'machine epsilon'
		eps = underflow;
		underflow /= 2.0;
	} while (underflow + 1.0 != 1.0);

	do {	// compute 'machine minimum'
		min = underflow;
		underflow /= 2.0;
	} while (underflow > 0.0);

	do {	// compute 'machine ypsilon'
		yps = overflow;
		overflow *= 2.0;
	} while (overflow + 1.0 != overflow);

	overflow -= 1.0;

	do {	// compute 'machine maximum'
		max = overflow;
		overflow *= 2.0;
	} while (overflow < INFINITY);

	kludge("-4503599627370495.5", between);
	kludge("            1.0e308", big);
	kludge("          -denormal", denormal);
	kludge("                  e", e);
	kludge("           -epsilon", epsilon);
	kludge("         indefinite", indefinite);
	kludge("          +infinity", infinity);
	kludge("          -infinity", big - infinity);
	kludge("    machine epsilon", eps);
	kludge("    machine maximum", max);
	kludge("    machine minimum", min);
	kludge("    machine ypsilon", yps);
	kludge("            maximum", maximum);
	kludge("           -minimum", minimum);
	kludge("                nan", nan);
	kludge("               null", null);
	kludge("            omicron", omicron);
	kludge("           overflow", overflow);
	kludge("                 pi", pi);
	kludge("          underflow", underflow);
	kludge("            ypsilon", ypsilon);
	kludge("               -0.0", zero);

	return indefinite == indefinite;
}
This program prints the following console output:
-4503599627370495.5 = -0x1.FFFFFFFFFFFFFp51	= -4503599627370495.5
            1.0e308 = +0x1.1CCF385EBC8A0p1023	= 1e+308
          -denormal = -0x0.0000000000001p-1022	= -5e-324
                  e = +0x1.5BF0A8B145769p1	= 2.718281828459045
           -epsilon = -0x1.0000000000000p-52	= -2.220446049250313e-16
         indefinite = -0x1.8000000000000p1024	= ind
          +infinity = +0x1.0000000000000p1024	= inf
          -infinity = -0x1.0000000000000p1024	= -inf
    machine epsilon = +0x1.0000000000000p-52	= 2.220446049250313e-16
    machine maximum = +0x1.FFFFFFFFFFFFFp1023	= 1.7976931348623157e+308
    machine minimum = +0x0.0000000000001p-1022	= 5e-324
    machine ypsilon = +0x1.0000000000000p52	= 4503599627370496
            maximum = +0x1.FFFFFFFFFFFFFp1023	= 1.7976931348623157e+308
           -minimum = -0x1.0000000000000p-1022	= -2.2250738585072014e-308
                nan = -0x1.8000000000000p1024	= ind
               null = +0x0.0000000000000p-1022	= 0
            omicron = +0x1.FFFFFFFFFFFFFp-1	= 0.9999999999999999
           overflow = +0x1.0000000000000p1024	= inf
                 pi = +0x1.921FB54442D18p1	= 3.141592653589793
          underflow = +0x0.0000000000000p-1022	= 0
            ypsilon = +0x1.0000000000000p52	= 4503599627370496
               -0.0 = -0x0.0000000000000p-1022	= -0
Note: printing the special floating-point values indefinite, ±infinity, ±0, quiet and signaling NANs as the character strings ind or nan(ind), +inf, -inf, +0, -0, nan and nan(snan) respectively is left as an exercise to the reader.

Implementation

The header file NOMSVCRT.H and the object library NOMSVCRT.LIB implement the following helper routines, internal functions and intrinsics supported and used by Microsoft’s Visual C compilers.

Startup Routines

The startup routines alias entry-point functions mainCRTStartup(), wmainCRTStartup(), WinMainCRTStartup(), wWinMainCRTStartup() and _DllMainCRTStartup() call the conventional main() functions main(), wmain(), WinMain(), wWinMain() and DllMain() respectively.

Note: their command line processing and argument splitting is feature bug-compatible to the MSVCRT runtime libraries and the Win32 function CommandLineToArgvW(): an unpaired double quote " neither aborts nor yields a Win32 error like 160 alias ERROR_BAD_ARGUMENTS or 1639 alias ERROR_INVALID_COMMAND_LINE, it is but (silently) closed at the end of the command line!

Note: when STDOUT or STDERR is redirected to an empty (new) file, wmainCRTStartup(), the startup routine for Unicode console programs, writes a Unicode BOM.

Note: when executed in a process with an own console window, the console program startup routines mainCRTStartup() and wmainCRTStartup() wait for a keypress before they exit and the console window closes; to indicate this wait state they beep once and flash the title bar of their console window after the main() respectively the wmain() function returns to the startup routine.

Note: the startup routines are implemented for all processor architectures supported by Windows NT.

Stack Allocation and Runtime Checks

_alloca(), _chkstk() and __security_check_cookie().

Note: contrary to the stack allocation routines shipped with the MSVCRT runtime libraries for the I386 alias x86 processor architecture, _alloca() and _chkstk() don’t touch already committed stack pages.

Note: the _alloca() and _chkstk() functions are implemented only for the I386 alias x86 and the AMD64 alias x64 processor architecture.

Note: the /GS runtime check routines are implemented for all processor architectures supported by Windows NT; they raise an exception 0xC0000409 alias STATUS_STACK_BUFFER_OVERRUN upon detection of a corrupted stack cookie.

Note: Windows’ module loader overwrites the default stack cookie (0xBB40E64E=3141592654=π×109 for 32-bit execution environment, 0x00002B992DDFA232=π×1018÷216 for 64-bit execution environment) of DLLs since Windows XP SP2 and that of applications since Windows 10 with a random value.

Signed 64-bit Integer Arithmetic for 32-bit Execution Environment

The (almost) undocumented helper routines _alldiv(), _alldvrm(), _allmul(), _allrem(), _allshl() and _allshr() are called for signed 64-bit integer arithmetic and shift operations on the I386 alias x86 processor architecture; the additional functions _allabs(), _allneg(), _allrol() and _allror() are provided just for fun.

Note: measured on processors of the Intel® Corei family, the signed 64÷64-bit division routines are about 7× to 11× faster than those supplied in the MSVCRT runtime libraries, and from about 2× to just slightly slower than native signed 128÷64-bit division in the 64-bit execution environment; 64×64-bit multiplication is about 4× slower than native 64×64-bit multiplication in the 64-bit execution environment.

The functions Int32x32To64(), Int32x32To64Div32() alias __emuldiv(), Int32x32To64Rem32() alias __emulmod(), Int64Div32() alias __ediv() and Int64Rem32() alias __emod() complement the __emul() intrinsic; they are defined as inline functions in the header file NOMSVCRT.H and implemented only for the I386 alias x86 processor architecture.

Unsigned 64-bit Integer Arithmetic for 32-bit Execution Environment

The (almost) undocumented helper routines _aulldiv(), _aulldvrm(), _aullrem() and _aullshr() are called for unsigned 64-bit integer arithmetic and shift operations on the I386 alias x86 processor architecture; the additional functions _aullmul(), _aullrol(), _aullror() and _aullshl() are provided just for fun.

Note: measured on processors of the Intel® Corei family, the unsigned 64÷64-bit division routines are about 7× to 11× faster than those supplied in the MSVCRT runtime libraries, and from less than 2× slower to even 20 % faster than native unsigned 128÷64-bit division in the 64-bit execution environment; 64×64-bit multiplication is about 4× slower than native 64×64-bit multiplication in the 64-bit execution environment.

The functions UInt32x32To64(), UInt32x32To64Div32() alias __emuldivu(), UInt32x32To64Rem32() alias __emulmodu(), UInt64Div32() alias __edivu() and UInt64Rem32() alias __emodu() complement the __emulu() intrinsic; they are defined as inline functions in the header file NOMSVCRT.H and implemented only for the I386 alias x86 processor architecture.

64-bit Integer Arithmetic

The functions _div64() and _udiv64(), since Visual C 2019 available as intrinsics only for the I386 alias x86 and the AMD64 alias x64 processor architecture, are implemented for the I386 alias x86 and the AMD64 alias x64 processor architecture.

128-bit Integer Arithmetic for 32-bit Execution Environment

The functions __mulh() alias MultiplyHigh(), __umulh() alias UnsignedMultiplyHigh(), _mul128() alias Multiply128() and _umul128() alias UnsignedMultiply128(), available as intrinsics only for the AMD64 alias x64 processor architecture, are implemented for the I386 alias x86 processor architecture.

128-bit Integer Arithmetic

The functions _div128() and _udiv128(), since Visual C 2019 available as intrinsics only for the AMD64 alias x64 processor architecture, are implemented for the I386 alias x86 and the AMD64 alias x64 processor architecture; they complement the functions and intrinsics _mul128() alias Multiply128() and _umul128() alias UnsignedMultiply128().

Note: measured on processors of the Intel® Core2 family, the _udiv128() function runs in the 32-bit execution environment about 5 % to 50 % slower than the _udiv128() intrinsic in the 64-bit execution environment.

128-bit Shift and Rotation

The functions __shiftleft128() alias ShiftLeft128() and __shiftright128() alias ShiftRight128(), available as intrinsics only for the AMD64 alias x64 processor architecture, are implemented for all (other) processor architectures supporting shift operations on 64-bit integers.

The functions __rotateleft128() and __rotateright128() complement the functions and intrinsics __shiftleft128() and __shiftright128(); they are defined as inline functions for all processor architectures supporting shift operations on 64-bit integers.

Note: on the I386 alias x86 and the AMD64 alias x64 processor architecture, shift and rotation counts from 0 to 64 are supported and performed modulo 64; on other processor architectures shift and rotation counts from 1 to 63 are supported.

Floating-Point Functions

_CIacos(), _CIasin(), _CIatan(), _CIatan2(), _CIcos(), _CIcosh(), _CIexp(), _CIfmod(), _CIlog(), _CIlog10(), _CIpow(), _CIsin(), _CIsinh(), _CIsqrt(), _CItan(), _CItanh(), _ftol(), _ftol2(), _ftol2_sse(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(), cbrt(), ceil(), copysign(), cos(), cosh(), exp(), exp2(), expm1(), fabs(), fdim(), floor(), fmax(), fmin(), fmod(), frexp(), hypot(), ilogb(), ldexp(), logb(), log(), log1p(), log2(), log10(), lrint(), llrint(), modf(), pow(), remainder(), remquo(), rint(), round(), scalbn(), _scalb(), sin(), sinh(), sqrt(), tan(), tanh() and trunc(), plus acot(), acot2(), acoth(), cot(), coth(), exp10(), frexp10(), ldexp10(), pown() and signbit().

Note: the floating-point routines support only the double-precision floating-point data type double.

Note: the floating-point routines are implemented only for the I386 alias x86 processor architecture; they use the algebraic, arithmetic, transcendental and trigonometric functions of the processor’s builtin IEEE754 FPU.

Note: the (almost) undocumented internal functions _CI*() implement the respective intrinsics on the I386 alias x86 processor architecture; calls to these functions are generated when the command line switches /fp:fast or /fp:precise and /Oi or /O2 but not /Qfast_transcendentals are used, or equivalent #pragma directives are given.

Floating-Point to ASCII Character String Conversion

The function dtostr(), based on Florian Loitsch’ Grisu algorithm, converts a double-precision floating-point number into its (almost always shortest) printable decimal representation, like the %g and %G conversion specifiers of the printf() function.

ASCII Character String to Floating-Point Conversion

The function strtod() converts an ASCII character string [ ‹white space› ] [{ + | - }] ‹decimal digit› … [ . [ ‹decimal digit› … ]] [{ e | E } [{ + | - }] ‹decimal digit› … ], [ ‹white space› ] [{ + | - }] [ ‹decimal digit› … ] . ‹decimal digit› … [{ e | E } [{ + | - }] ‹decimal digit› … ], [ ‹white space› ] [{ + | - }] 0 { x | X } ‹hexadecimal digit› … [ . [ ‹hexadecimal digit› … ]] [{ p | P } [{ + | - }] ‹decimal digit› … ], [ ‹white space› ] [{ + | - }] 0 { x | X } [ ‹hexadecimal digit› … ] . ‹hexadecimal digit› … [{ p | P } [{ + | - }] ‹decimal digit› … ] or [ ‹white space› ] [{ + | - }] { infinity | INFINITY | inf | INF | nan | NAN } into a double-precision floating-point number.

Unicode Character String to Floating-Point Conversion

The function wcstod() converts an Unicode character string [ ‹white space› ] [{ + | - }] ‹decimal digit› … [ . [ ‹decimal digit› … ]] [{ e | E } [{ + | - }] ‹decimal digit› … ], [ ‹white space› ] [{ + | - }] [ ‹decimal digit› … ] . ‹decimal digit› … [{ e | E } [{ + | - }] ‹decimal digit› … ], [ ‹white space› ] [{ + | - }] 0 { x | X } ‹hexadecimal digit› … [ . [ ‹hexadecimal digit› … ]] [{ p | P } [{ + | - }] ‹decimal digit› … ], [ ‹white space› ] [{ + | - }] 0 { x | X } [ ‹hexadecimal digit› … ] . ‹hexedecimal digit› … [{ p | P } [{ + | - }] ‹decimal digit› … ] or [ ‹white space› ] [{ + | - }] { infinity | INFINITY | inf | INF | nan | NAN } into a double-precision floating-point number.

Integer to ASCII Character String Conversion

The functions itoa(), ltoa(), lltoa(), ultoa() and ulltoa() convert a signed or unsigned 32-bit or 64-bit integer number into its printable representation to bases from 2 to 36.

The functions ltostr(), ultostr(), lltostr() and ulltostr() convert a signed or unsigned 32-bit or 64-bit integer number into its (shortest) printable decimal representation.

Integer to Unicode Character String Conversion

The functions itow(), ltow(), lltow(), ultow() and ulltow() convert a signed or unsigned 32-bit or 64-bit integer number into its printable representation to bases from 2 to 36.

ASCII Character String to Integer Conversion

The functions strtol() and strtoll() convert an ASCII character string [ ‹white space› ] [{ + | - }] [ 0 [{ b | B | x | X }]] { ‹decimal digit› | ‹latin letter› } … into a signed 32-bit or 64-bit integer number.

The functions strtoul() and strtoull() convert an ASCII character string [ ‹white space› ] [ + ] [ 0 [{ b | B | x | X }]] { ‹decimal digit› | ‹latin letter› } … into an unsigned 32-bit or 64-bit integer number.

Note: strtoul() and strtoull() support only positive values, they don’t accept a − sign!

Unicode Character String to Integer Conversion

The functions wcstol() and wcstoll() convert an Unicode character string [ ‹white space› ] [{ + | - }] [ 0 [{ b | B | x | X }]] { ‹decimal digit› | ‹latin letter› } … into a signed 32-bit or 64-bit integer number.

The functions wcstoul() and wcstoull() convert an Unicode character string [ ‹white space› ] [ + ] [ 0 [{ b | B | x | X }]] { ‹decimal digit› | ‹latin letter› } … into a unsigned 32-bit or 64-bit integer number.

Note: strtoul() and strtoull() support only positive values, they don’t accept a − sign!

ASCII Character String Handling

strcat(), strchr(), strcmp(), strcpy(), strlen(), strncat(), strncmp(), strnset(), strrchr(), strrev(), strset(), strstr() and _strset().

Note: the ASCII character string handling routines are implemented only for the I386 alias x86 and the AMD64 alias x64 processor architecture.

Unicode Character String Handling

wcscat(), wcschr(), wcscmp(), wcscpy(), wcslen(), wcsncat(), wcsncmp(), wcsnset(), wcsrchr(), wcsrev(), wcsset(), wcsstr() and _wcsset().

Note: the Unicode character string handling routines are implemented only for the I386 alias x86 and the AMD64 alias x64 processor architecture.

ASCII Character Classification

The character classification functions isasciiA() alias isascii(), isalnumA() alias isalnum(), isalphaA() alias isalpha(), isblankA() alias isblank(), iscntrlA() alias iscntrl(), isdigitA() alias isdigit(), isgraphA() alias isgraph(), islowerA() alias islower(), isprintA() alias isprint(), ispunctA() alias ispunct(), isspaceA() alias isspace(), isupperA() alias isupper(), and isxdigitA() alias isxdigit() are defined as inline functions in the header file NOMSVCRT.H.

Unicode Character Classification

The character classification functions isasciiW() alias iswascii(), isalnumW() alias iswalnum(), isalphaW() alias iswalpha(), isblankW() alias iswblank(), iscntrlW() alias iswcntrl(), isdigitW() alias iswdigit(), isgraphW() alias iswgraph(), islowerW() alias iswlower(), isprintW() alias iswprint(), ispunctW() alias iswpunct(), isspaceW() alias iswspace(), isupperW() alias iswupper(), and isxdigitW() alias iswxdigit() are defined as inline functions in the header file NOMSVCRT.H.

Text Output

DebugFormat(), PrintBuffer(), PrintChar(), PrintFormat() and PrintString().
The Print*() functions return a non-zero value on success; on failure they return 0 and a Win32 error code for retrieval through the Win32 function GetLastError().

Note: these functions are available for ASCII and Unicode; their prototypes follow the conventions of the Windows SDK.

Note: the functions PrintBuffer(), PrintChar() and PrintFormat() are supported only in console programs.

Note: in order to prevent a mix of ASCII and UTF-16LE which may be rendered as mojibake, in ANSI console programs the Unicode functions PrintBufferW(), PrintCharW() and PrintFormatW(), and in Unicode console programs the ANSI functions PrintBufferA(), PrintCharA() and PrintFormatA(), write nothing when their output is redirected to a file, but return FALSE and yield Win32 error 1288 alias ERROR_INVALID_CRUNTIME_PARAMETER instead.

Note: the functions DebugFormat() and PrintFormat() truncate their output to 1024 (ASCII or Unicode) characters, support 64-bit integers only with the (undocumented) %…I64… instead of the %…ll… argument length modifier, don’t support the right alignment alias sign conversion flag %+… as well as the space conversion flag % …, and don’t support floating-point conversion specifiers %…a, %…A, %…e, %…E, %…f, %…F, %…g, %…G at all.

Buffer Manipulation

memchr(), memcmp(), memcpy(), memmove(), memset(), memmem() plus memswap(), and wmemchr(), wmemcmp(), wmemcpy(), wmemmove(), wmemset(), wmemmem() plus wmemswap().
Additionally lmemchr(), lmemcmp(), lmemcpy(), lmemmove(), lmemset() plus lmemswap(), and llmemchr(), llmemcmp(), llmemcpy(), llmemmove(), llmemset() plus llmemswap().

Note: for processor architectures other than I386 alias x86 and AMD64 alias x64, only the memmem() and wmemmem() functions are implemented.

Note: the lmem*() functions are implemented only for the I386 alias x86 and the AMD64 alias x64 processor architecture.

Note: the llmem*() functions are implemented only for the AMD64 alias x64 processor architecture.

Endian Conversion

htonll(), htonl(), htons(), ntohll(), ntohl(), ntohs() and swab().

Miscellaneous Functions

abs(), labs(), llabs(), max(), lmax(), llmax(), min(), lmin(), llmin(), sgn(), lsgn(), llsgn(), lzcnt32(), lzcnt64(), parity8(), parity16(), parity32(), parity64(), popcnt32(), popcnt64(), rev8(), rev16(), rev32(), rev64(), sqrt32(), sqrt64(), tzcnt32() and tzcnt64().

Note: most of these functions are defined as inline functions in the header file NOMSVCRT.H.

Note: the functions lzcnt32() and lzcnt64() don’t use the __lzcnt() intrinsics and are thus available on all processors.

Note: unlike the PopulationCount64() function defined in the header file WINNT.H of recent Windows SDKs, the functions popcnt32() and popcnt64() don’t use the __popcnt() intrinsics and are thus available on all processors.

Note: the functions tzcnt32() and tzcnt64() don’t use the _tzcnt_u32() and _tzcnt_u64() intrinsics and are thus available on all processors.

POSIX Functions

calloc(), free(), malloc() and realloc().

Random Number Generators

drbg32() and drbg64(), half32() and half64(), msqr32() and msqr64(), mwcg32() and mwcg64(), prng32() and prng64(), plus smcg32() and smcg64() return uniform distributed unsigned integers in the range 0 to 232−1 and 264−1 respectively; cntr32() and cntr64(), full32() and full64(), plus lfsr32() and lfsr64() return uniform distributed unsigned integers in the range 1 to 232−1 and 264−1 respectively.

Note: the generators are defined as inline functions in the header file NOMSVCRT.H.

The generators provided by the functions cntr32() and cntr64(), full32() and full64(), lfsr32() and lfsr64() are linear feedback shift registers alias Galois counters with period lengths of 232−1 and 264−1 respectively, while the XorShift generators half32() and half64() have period lengths of 264−1 and 2128−1 respectively.

The deterministic random bit generator provided by the functions drbg32() and drbg64() applies a (two-round multiplicative) hash function to a (modular) arithmetic progression alias Weyl sequence; its period length is 232 and 264 respectively.

Note: the (alias) name Weyl sequence for a (modular) arithmetic progression was coined by George Marsaglia while introducing XorShift pseudo-random number generators.

The pseudo-random number generator provided by the functions msqr32() and msqr64() combines John von Neumann’s middle-square method with a (modular) arithmetic progression alias Weyl sequence to overcome the well-known deficiencies of the middle-square method, as originally devised by Bernard Widynski, following a proposal of Richard Peirce Brent.

Note: contrary to his 32-bit only implementation, which is not based on the middle-square method, but combines a pure quadratic (non-linear) congruential generator with a pure additive (linear) congruential generator and an invertible mapping, msqr32() and msqr64() use the true middle of the square instead of just its lower half and perform a byte-swap instead of the rotation.

The pseudo-random number generator provided by the functions mwcg32() and mwcg64() is George Marsaglia’s multiply-with-carry generator.

The pseudo-random number generator provided by the functions prng32() and prng64() is Bob Jenkins’ small fast generator.

The pseudo-random number generator provided by the functions smcg32() and smcg64() is a multiplicative (linear) congruential generator, invented by Derrick Henry Lehmer, with scrambled output, as originally devised by Melissa O'Neill.

The following table shows the execution times of some of these functions on different 64-bit processors in clock cycles per item; the upper half for the 32-bit execution environment, the lower half for the 64-bit execution environment.

half32() half64() msqr32() msqr64() mwcg32() mwcg64() smcg32() smcg64() prng32() prng64()
AMD® Ryzen5 3600 4 12 14 15 3 10 9 16 5 22
AMD® Ryzen7 2700X 4 13 14 9 4 12 9 20 5 26
Intel Core i5-8400 6 10 13 12 7 16 9 16 6 20
Intel Core i5-6600 5 9 12 11 6 15 8 15 6 19
Intel Core i5-4670 6 9 13 14 7 18 9 17 5 20
Intel Core2 P8700 5 10 13 19 6 18 8 19 5 25
Intel Core2 Q8400 5 9 13 19 6 18 8 19 5 24
AMD® Ryzen5 3600 3 4 6 9 3 3 4 5 4 4
AMD® Ryzen7 2700X 3 5 3 7 2 4 3 6 2 4
Intel Core i5-8400 4 6 5 10 3 5 3 6 3 6
Intel Core i5-6600 4 6 5 10 3 5 3 6 3 6
Intel Core i5-4670 3 5 5 8 2 4 3 6 2 5
Intel Core2 P8700 5 6 15 15 10 7 10 9 5 5
Intel Core2 Q8400 5 6 15 15 10 7 10 9 5 5

Note: the 64-bit pseudo-random number generators drbg64(), msqr64(), prng64() and smcg64() pass a full 32 TB run of the PractRand test suite version 0.94.

Download

… the makefile NOMSVCRT.MAK to build the object library NOMSVCRT.LIB for the I386 alias x86 processor architecture, the optional icon file NOMSVCRT.ICO to build the resource file NOMSVCRT.RES, the header file NOMSVCRT.H, and the ANSI C source file NOMSVCRT.C to build the sample Windows application NOMSVCRT.EXE, the sample DLL NOMSVCRT.DLL, and the sample console program NOMSVCRT.COM, …

Authenticity and Integrity

The sample Windows application NOMSVCRT.EXE, the sample DLL NOMSVCRT.DLL, and the sample console program NOMSVCRT.COM are digitally signed using a (self-issued) X.509 leaf certificate and time stamped.

Download and install the (self-signed) X.509 root certificate to validate and verify the digital certificate and the signature.

Contact

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2020 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>