When compiling with a specific vendor's implementation of the C language, and related libraries, be aware that, unfortunately, standards conformance can differ from vendor to vendor. Be certain to read your vendor's documentation to reduce the likelihood of accidentally relying on implementation-specific behavior or deviations.

Implementation-Specific Deviations

Implementation-specific deviations are listed below. The Version column lists the latest version of the compiler or library that exhibits the behavior.

Microsoft Visual Studio

APIDescriptionVersion 
Variable-length arraysAbsent 2012 
static and type qualifiers in
parameter array declarators
Absent 2012 
_Static_assertAbsent; can use static_assert, as in C++112012
_NoreturnAbsent; can use __declspec(noreturn)2012
inlineAbsent; can use __inline2012 
Hexadecimal floating-point constantsAbsent 2012 
Compound literalsAbsent 2012 
Designated initializersAbsent 2012 
Implicit function declarationsSupport was removed in C11, but it is still supported in MSVC (with diagnostic) 2012 
Mixed declarations and codeAbsent 2012 
_Pragma
Absent; can use __pragma2012 
_BoolAbsent2012 
_ComplexAbsent 2012 
__func__Absent; can use __FUNCTION__2012

idempotent type qualifiers

Diagnosed, but functional2012
_Thread_localAbsent; can use __declspec(thread)
<complex.h>Absent; __STDC_NO_COMPLEX__ is not defined2012 
isblank()Absent2012 
<fenv.h>Absent2012 
<inttypes.h>Absent2012 

float_t, double_t, HUGE_VALF,
HUGE_VALL, INFINITY, NAN

Absent 2012 
#pragma FP_CONTRACTSpelled fp_contract instead of FP_CONTRACT2012 
fpclassify()Absent, use _fpclass() instead2012 
isfinite(), isinf()Absent, use _finite() or _finitef()instead2012 
isnan()Absent, use _isnan() or _isnanf() instead2012
isnormal()Absent, use _fpclass() instead 2012
signbit()Absent 2012 
acosh(), asinh(), atanh()Absent2012 
exp2(), expm1(), ilogb(), log1p(),
log2()
Absent2012 
scalbn()Absent; use _scalb() (or _scalbf() on x64 targets only) instead 2012 
cbrt()Absent 2012 
erf(), erfc(), lgamma(), tgamma()Absent2012
nearbyint(), rint(), lrint(),
round(), lround(), trunk()
Absent 2012
remainder(), remquo()Absent2012 
copysign()Absent; use _copysign() instead 2012 
nan(), nexttoward()Absent 2012 
nextafter()Absent; use _nextafter() or _nextafterf() instead 2012 
fdim()fmax(), fmin()Absent 2012 
fma()Absent 2012
isgreater(), isgreaterequal(),
isless(), islessequal(),
isunordered()
Absent 2012 
<stdalign.h>Absent 
va_copy()Absent 2012 
<stdatomic.h>Absent; __STDC_NO_ATOMICS__ is not defined2012 
<stdbool.h>Absent; _Bool is not supported in /TC mode, but bool is supported in /TP mode2012 
max_align_tAbsent 2012 
Printing format specifier type fieldS is MSVC-specific; c, s, and z are not conforming [ISO/IEC 9899-2011]; F is unsupported2012
Printing format specifier size fieldII32 and I64 are MSVC-specific; hw and l are not conforming [ISO/IEC 9899-2011]; hh, jz
and t unsupported
2012
Scanning format specifier type fieldS is MSVC-specific; c and s are not conforming [ISO/IEC 9899-2011]; p is unsupported2012 
Scanning format specifier size fieldI64 is MSVC-specific; h, l, and L prefixes are not conforming [ISO/IEC 9899-2011]; hh, j, z, and
t are unsupported
2012 
snprintf()Absent; beware that _snprintf()'s semantics are sufficiently different that it is not advisable as a replacement2012
vfscanf(), vscanf(), vsscanf()Absent 2012 
fopen(), freopen()Mode parameter not conforming [ISO/IEC 9899-2011]; t, c, n, N, S, R, TD and css are MSVC
extensions; x is unsupported; see remarks
2012 
atoll()Absent; use _atoi64() instead 2012 
strtof(), strtold()Absent 2012
strtoll()Absent; use _strtoi64() instead 2012 
strtoull()Absent; use _strtoui64() instead 2012 
aligned_alloc()Absent; use _aligned_malloc() instead (beware, the parameter order is reversed)2012 
at_quick_exit(), quick_exit()Absent 2012 
_Exit()Absent; use _exit() instead2012
<stdnoreturn.h>Absent; use __declspec(noreturn) instead 2012 
<tgmath.h>Absent 2012 
<threads.h>Absent; __STDC_NO_THREADS__ is not defined2012 
TIME_UTC, struct timespec,
timespec_get()
Absent2012 
strftime(), wcsftime()z is not conforming [ISO/IEC 9899-2011]; C, D, e, F, gG, h, n, r, R, tT, uV unsupported2012
<uchar.h>Absent 2012 
vfwscanf(), vswscanf(), vwscanf()Absent2012 
fwide()Unsupported 2012 
wcstof(), wcstold()Absent 2012 
wcstoll()Absent; use _wcstoi64() instead 2012 
wcstoull()Absent; use _wcstoui64() instead2012 
iswblank()Absent 2012 
FLT_EVAL_METHOD, *_HAS_SUBNORM,
*_DECIMAL_DIG, *_TRUE_MIN
Absent 2012 
__STDC_LIB_EXT1__,
__STDC_WANT_LIB_EXT1__
Not defined; instead, MSVC uses __STDC_SECURE_LIB__ and __STDC_WANT_SECURE_LIB__2012 
fopen_s(), freopen_s()Uses the same mode strings as fopen()u prefix is unsupported; see remarks2012 
vfscanf_s(), vscanf_s(),
vsscanf_s()
Absent 2012 
constraint_handler_t,
set_constraint_handler_s(),
abort_handler_s(),
ignore_handler_s()
Absent; use _invalid_parameter_handler and _set_invalid_parameter_handler()
instead.  Beware that the _invalid_parameter_handler signature is considerably different than
that of constraint_handler_t.  No replacement for abort_handler_s() or
ignore_handler_s()
2012 
bsearch_s()Not conforming [ISO/IEC 9899-2011]; beware that the comparison function pointer's signature is
different from the standard; namely that the context parameter comes first in MSVC but last in ISO C
2012 
qsort_s()Not conforming [ISO/IEC 9899-2011]; beware that the comparison function's pointer signature is different
from the standard; namely that the context parameter comes first in MSVC but last in ISO C
2012
strtok_s()Not conforming [ISO/IEC 9899-2011]; the function signature is missing the rsize_t * parameter2012 
memset_s(), strerrorlen_s() Absent 2012
gmtime_s(), localtime_s()Not conforming [ISO/IEC 9899-2011]; the function signature has the parameters reversed and returns
errno_t instead of struct tm *
2012
snwprintf_s()Absent; use _snwprintf_s() instead.  Note that the parameters differ from the ISO C signature2012
vfwscanf_s(), vswscanf_s(),
vwscanf_s()
Absent2012

vsnwprintf_s()

Absent, use _vsnwprintf_s() instead.  Note that the parameters differ from the ISO C signature2012 
wcstok_s()Not conforming [ISO/IEC 9899-2011]; the function signature is missing the rsize_t * parameter2012 

fopen() & freopen()

The C standard does not specify what happens with Windows newline characters (CRLF), and so care should be taken when working with text files.  For instance:

#include <stdio.h>
 
void func( void ) {
  FILE *fp = fopen("text_file.txt", "r");
  if (fp) {
    int counter = 0;
    while (!feof(fp) && !ferror(fp)) {
      ++counter;
      (void)fgetc(fp);
    }
    fclose(fp);
    printf("Number of characters read: %d\n", counter);
  }
}

 
// Contents of text_file.txt
This has
CRLF newlines
in it.

If you save the contents of text_file.txt with Windows line endings (CRLF) and run the program on Windows, it will print 30. However, if you compile the application on a platform which does not use CRLF as its line endings, it will print 32. This is because MSVC's text translation mode will translate the CRLF characters into a single LF character on input, and translate a single LF character to CRLF on output. To ensure consistent behavior between platforms, consider opening the file in binary translation mode explicitly.

#include <stdio.h>
 
void func( void ) {
  FILE *fp = fopen("text_file.txt", "rb");
  if (fp) {
    int counter = 0;
    while (!feof(fp) && !ferror(fp)) {
      ++counter;
      (void)fgetc(fp);
    }
    fclose(fp);
    printf("Number of characters read: %d\n", counter);
  }
}

 This program will print 32 with the given text, regardless of platform.

Risk Assessment

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC23-C

High

Probable

Medium

P12

L1

Automated Detection

Tool

Version

Checker

Description

Astrée
24.04

Supported: Astrée reports non-standard language elements.
CodeSonar
8.1p0

BADFUNC.ABORT_HANDLER_S
BADFUNC.ATOLL
BADFUNC.BSEARCH_S
BADFUNC.CONSTRAINT_HANDLER_T
BADFUNC.FENV_H
BADFUNC.FOPEN_S
BADFUNC.FREOPEN_S
BADFUNC.GMTIME_S
BADFUNC.IGNORE_HANDLER_S
BADFUNC.LOCALTIME_S
BADFUNC.MEMSET_S
BADFUNC.SET_CONSTRAINT_HANDLER_S
BADFUNC.SNWPRINTF_S
BADFUNC.STRERRORLEN_S
BADFUNC.STRTOK_S
BADFUNC.VFSCANF_S
BADFUNC.VFWSCANF_S
BADFUNC.VSCANF_S
BADFUNC.VSNWPRINTF_S
BADFUNC.VSSCANF_S
BADFUNC.VSWSCANF_S
BADFUNC.VWSCANF_S
BADFUNC.WCSTOK_S
CONCURRENCY.C_ATOMIC
CONCURRENCY.THREADLOCAL
LANG.FUNCS.NORETURN
LANG.PREPROC.INCL.TGMATH_H
LANG.STRUCT.ALIGNAS
LANG.STRUCT.ALIGNAS.EZA
LANG.STRUCT.ALIGNAS.IAS
LANG.STRUCT.ALIGNAS.TMAS
LANG.STRUCT.ALIGNOF
LANG.STRUCT.DECL.IMPFN
LANG.STRUCT.DECL.VLA
LANG.STRUCT.INIT.UADI
LANG.TYPE.VMAT
MATH.RANGE.GAMMA

Use of abort_handler_s
Use of atoll
Use of bsearch_s
Use of constraint_handler_t
Use of <fenv.h> Exception Handling Function
Use of fopen_s
Use of freopen_s
Use of gmtime_s
Use of ignore_handler_s
Use of localtime_s
Use of memset_s
Use of set_constraint_handler_s
Use of snwprintf_s
Use of strerrorlen_s
Use of strtok_s
Use of vfscanf_s
Use of vfwscanf_s
Use of vscanf_s
Use of vsnwprintf_s
Use of vsscanf_s
Use of vswscanf_s
Use of vwscanf_s
Use of wcstok_s
Use of C Atomic
Use of Thread Local
Use of Noreturn
Use of <tgmath.h>
Use of Alignas
Explicit Zero Alignment
Inconsistent Alignment Specifications
Too Many Alignment Specifiers
Use of Alignof
Implicit Function Declaration
Declaration of Variable Length Array
Unspecified Array Size with Designator Initialization
Pointer to Variably-modified Array Type
Gamma on Zero


2 Comments

  1. Instead of having a separate column for link, why not just link the appropriate term?

    I don't think you want to compare to "ANSI" or "ISO C".  Probably should reference a specific ISO/IEC version of the standard.

    1. Both good suggestions, I'll modify in the next round of updates.  Thanks!