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
Link | Format specifier type field | c , s , and z are not ANSI compatible; F unsupported | 2012 | MSDN |
Format specifier size field | I , I32 and I64 are MSVC-specific; h , w and l are not ANSI compatible; hh , j , z and t unsupported | 2012 | Variable-length arrays | Absent | 2012 |
static and type qualifiers in parameter array declarators | Absent | 2012 |
_Static_assert | Absent; can use static_assert , as in C++11 | 2012 |
_Noreturn | Absent; can use __declspec(noreturn) | 2012 |
inline | Absent; can use __inline | 2012 |
Hexadecimal floating-point constants | Absent | 2012 |
Compound literals | Absent | 2012 |
Designated initializers | Absent | 2012 |
Implicit function declarations | Support was removed in C11, but it is still supported in MSVC (with diagnostic) | 2012 |
Mixed declarations and code | Absent | 2012 |
_Pragma
| Absent; can use __pragma | 2012 |
_Bool | Absent | 2012 |
_Complex | Absent | 2012 |
__func__ | Absent; can use __FUNCTION__ | 2012 |
idempotent type qualifiers | Diagnosed, but functional | 2012 |
_Thread_local | Absent; can use __declspec(thread) |
MSDN |
|
<complex.h> | Absent; __STDC_NO_COMPLEX__ is |
defined | | float_t , double_t , HUGE_VALF, HUGE_VALL, INFINITY, NAN
| Absent | 2012 |
|
#pragma FP_CONTRACT | Spelled fp_contract instead of FP_CONTRACT | 2012 |
MSDNMSDN | isfinite() , isinf() | Absent, use _finite() or _finitef() instead | 2012 |
MSDN |
isnan() | Absent, use _isnan() or _isnanf() instead | 2012 |
MSDN | MSDN |
acosh() , asinh() , atanh() | Absent | 2012 |
| exp2() , expm1() , ilogb() , log1p() ,
log2() | Absent | 2012 |
|
scalbn() | Absent; use _scalb() (or _scalbf() on x64 targets only) instead | 2012 |
MSDN | |
erf() , erfc() , lgamma() , tgamma() | Absent | 2012 |
|
nearbyint() , rint() , lrint() ,
round() , lround() , trunk() | Absent | 2012 |
| remainder() , remquo() | Absent | 2012 |
MSDN | nan() , nexttoward() | Absent | 2012 |
|
nextafter() | Absent; use _nextafter() or _nextafterf() instead | 2012 |
MSDN |
fdim() , fmax(), fmin() | Absent | 2012 |
| |
isgreater() , isgreaterequal() ,
isless() , islessequal() ,
isunordered() | Absent | 2012 |
<stdalign.h> | Absent |
|
va_copy() | Absent | 2012 |
<stdatomic.h> | Absent; |
<stdalign.h> | Absent | | |
__STDC_NO_ATOMICS__ is not defined | 2012 |
<stdbool.h> | Absent; _Bool is not supported in /TC mode, but bool is supported in /TP mode | 2012 |
max_align_t | Absent | 2012 |
Printing format specifier type field | S is MSVC-specific; c , s , and z are not conforming [ISO/IEC 9899-2011]; F is unsupported | 2012 |
Printing format specifier size field | I , I32 and I64 are MSVC-specific; h , w and l are not conforming [ISO/IEC 9899-2011]; hh , j , z
and t unsupported | 2012 |
Scanning format specifier type field | S is MSVC-specific; c and s are not conforming [ISO/IEC 9899-2011]; p is unsupported | 2012 |
Scanning format specifier size field | I64 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 replacement | 2012 |
vfscanf() , vscanf() , vsscanf() | Absent | 2012 |
fopen() , freopen() | Mode parameter not conforming [ISO/IEC 9899-2011]; t , c , n , N , S , R , T , D 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() instead | 2012 |
<stdnoreturn.h> | Absent; use __declspec(noreturn) instead | 2012 |
<tgmath.h> | Absent | 2012 |
<threads.h> | Absent; __STDC_NO_THREADS__ is not defined | 2012 |
TIME_UTC, struct timespec,
timespec_get() | Absent | 2012 |
strftime(), wcsftime() | z is not conforming [ISO/IEC 9899-2011]; C , D , e , F , g , G , h , n , r , R , t , T , u , V unsupported | 2012 |
<uchar.h> | Absent | 2012 |
vfwscanf() , vswscanf() , vwscanf() | Absent | 2012 |
fwide() | Unsupported | 2012 |
wcstof() , wcstold() | Absent | 2012 |
wcstoll() | Absent; use _wcstoi64() instead | 2012 |
wcstoull() | Absent; use _wcstoui64() instead | 2012 |
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 remarks | 2012 |
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 * parameter | 2012 |
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 signature | 2012 |
vfwscanf_s() , vswscanf_s() ,
vwscanf_s() | Absent | 2012 |
vsnwprintf_s()
| Absent, use _vsnwprintf_s() instead. Note that the parameters differ from the ISO C signature | 2012 |
wcstok_s() | Not conforming [ISO/IEC 9899-2011]; the function signature is missing the rsize_t * parameter | 2012 |
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:
Code Block |
---|
|
#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.
Code Block |
---|
|
#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 | |
| Supported: Astrée reports non-standard language elements. |
CodeSonar | | 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 |
Image Added Image Added Image Added