I'm wondering how widely are __func__ (part of C99, but I'm compiling as C89) and __FUNCTION__ supported.
I have an old code base that is mostly using manual const char* id; variables that are then passed to various (mostly logging) functions. I would like to get rid of this and move the function name into a macro.
The predefined identifier __func__ was added to the 1999 ISO C standard; the older 1990 C standard doesn't have it.
Support for __func__ in pre-C99 compilers will depend on which compiler you're using.
Modern versions of gcc support __func__ even in C90 mode (-ansi or -std=c89).
Before __func__ was added to the standard, gcc implemented its own equivalent extension, but with the name __FUNCTION__. (gcc also supports __PRETTY_FUNCTION__, which is identical to __func__ and __FUNCTION__ for C, but provides more information in C++.)
The gcc manual gives some advice:
__FUNCTION__ is another name for __func__. Older versions of GCC recognize only this name. However, it is not standardized. For maximum
portability, we recommend you use __func__, but provide a fallback
definition with the preprocessor:
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
which implies that gcc added support for __FUNCTION__ in version 2. gcc 2.0 was released in 1992; you're very unlikely to be using a version of gcc that doesn't support at least __FUNCTION__, if not __func__.
Note that since __func__ and __FUNCTION__ are predefined identifiers, not macros, you only need the #define once, not in each function. On the other hand, you can't use #ifdef __func__ or #ifdef __FUNCTION__ to detect the level of support.
As for other compilers, a quick experiment indicates that Microsoft Visual C++ 2010 Express supports __FUNCTION__, but not __func__ or __PRETTY_FUNCTION__, when compiling C code. The above block of code from the gcc manual compiles under MSVC, but it results in __func__ being defined as "<unknown>". It shouldn't be too difficult to adjust it to recognize that MSVC supports __FUNCTION__. (I don't know whether older versions do so.) You can probably use the predefined macro _MSC_VER for this. Microsoft's documentation says that support for __FUNCTION__ goes back at least to the 2003 release, which sets _MSC_VER to 1300, so changing the second line to
# if __GNUC >= 2 || _MSC_VER >= 1300
is a good start. (It may well have been supported in earlier releases.)
For compilers other than gcc and MSVC, you'll have to consult their respective documentation -- but in any case, the block of code recommended in the gcc manual should work for any compiler, at worst falling back to "<unknown>".
The boost current_function.hpp header contains several #defines for the ways to get the current function on different platforms.
That's not to say that those platforms don't support other ways of getting the current function, but the choices made for boost are likely to represent nice (if not the nicest) ways of getting the information on those platforms.
An adaptation of this header for your code (and for C) could well be what you need.
I believe it is regardless what C standard is used (if C89 or C99). The more important factor is the compiler being used since it is the one that will implement __func__. The latest GCC compilers will add __func__ no matter the standard being used. I think. :)
Related
Since a quick Google search did not find anything, I will try to ask here (since many people involved in gcc/clang hang around here) - What is the status of __STDC_LIB_EXT1__ in gcc/clang? We are developing a cross platform applicataion and I wanted to use some of the safe bounds checking functions from <stdio.h> (which by miracle are available on Visual Studio 2017), but could not compile the code with Xcode 9.2. I assumed maybe the clang version Xcode uses is outdated, but gcc 6.3.0 on Ubuntu behaves the same. I am trying to use tmpnam_s with the following sample:
#if defined(__STDC_LIB_EXT1__)
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#else
#error "__STDC_LIB_EXT1__ not defined"
#endif
int main(int argc, char** argv)
{
char t[L_tmpnam_s];
tmpnam_s(t, L_tmpnam_s);
return 0;
}
But the compilation fails with the macro not being defined:
gcc -std=c11 test.c
test.c:5:2: error: #error "__STDC_LIB_EXT1__ not defined"
#error "__STDC_LIB_EXT1__ not defined"
^~~~~
Am I doing something wrong or this function set is simply poorly supported?
The whole set of 'safe' functions with the _s suffixes is poorly supported. Microsoft wrote a set of functions with the _s suffixes and submitted that to the C standard committee to be standardized. The committee made some changes (arguably out of necessity), and created a technical report, TR 24731-1. A mildly modified version of the TR was included as optional Annex K (normative) in the C11 standard, ISO/IEC 9899:2011.
You can find many sordid details in the answers to Do you use the TR-24731 "safer" functions?, especially in the notes in my answer to that question, and especially the link to the Standard C committee document N1967 Field Experience with Annex K — Bounds Checking Interfaces.
I don't know what the current status of the N1967 proposal is, but that it was suggested is telling. N1967 also contains links to libraries that support Annex K / TR-24731-1 — the list is limited.
Note that Microsoft does not implement the library specified by the C11 standard. It implements an approximation to the standard, but there are crucial differences. This would matter more if any other system had implemented the standard — but the functions have not been implemented in any widely accepted form (so, for example, the GNU C Library does not and will not support them).
C99 added a macro __STDC_IEC_559__ which can be used to test if a compiler and standard library conform to the ISO/IEC/IEEE 60559 (or IEEE 754) standard.
According to the answers for this question
how-to-check-that-ieee-754-single-precision-32-bit-floating-point-representation most C compilers don't set the preprocessor macro __STDC_IEC_559__.
According to GCC's documentation it does not define __STDC_IEC_559__.
I tested this with GCC 4.9.2 and Clang 3.6.0 both using with glibc 2.21 using the following code.
//test.c
//#include <features.h>
int main(void) {
#if defined ( __STDC_IEC_559__ )
//#if defined ( __GCC_IEC_559__ )
return 1;
#else
return 0;
#endif
}
and then
echo $?
This shows that with this code __STDC_IEC_559__ is defined with GCC but not with Clang. I then did gcc -E and it showed that the file stdc-predef.h is included. This file defines __STDC_IEC_559__.
/* glibc's intent is to support the IEC 559 math functionality, real
and complex. If the GCC (4.9 and later) predefined macros
specifying compiler intent are available, use them to determine
whether the overall intent is to support these features; otherwise,
presume an older compiler has intent to support these features and
define these macros by default. */
#ifdef __GCC_IEC_559
# if __GCC_IEC_559 > 0
# define __STDC_IEC_559__ 1
# endif
#else
# define __STDC_IEC_559__ 1
#endif
This confirms that it's glibc that defines this macro and not GCC.
However, when I include features.h (or stdio.h) this file is included by Clang as well and that __STDC_IEC_559__ is defined.
So __STDC_IEC_559__ is defined by both GCC and Clang (with a glibc header file) which seems to disagree with the answer to the first question I linked to.
I then tested musl (e.g. musl-gcc -test.c) which is a different standard library than glibc. This showed that __STDC_IEC_559__ is not defined with musl.
As I understand it the standard C library does not define the basic floating point algebra. For example the standard C library does not define the result of 1.0/-0.0. This is defined by the compiler.
My questions are (ranked in order of importance to me):
Why is __STDC_IEC_559__ defined by glibc and not by the compiler?
If I made my own standard library and I wanted to define __STDC_IEC_559__ I would need to know that the compiler already conforms to IEEE 754 for operations not defined in my standard library (e.g 1.0/-0.0). Is there documentations for this or a macro to test for this?
Wikipedia states that "users should be aware that this macro (__STDC_IEC_559__) is sometimes defined while it shouldn't be". Is this statement still accurate?
I believe __STDC_IEC_559__ relies on some library features and can't be defined solely by the compiler. See this post for some information. This is not uncommon for C -- the compiler and the C library must sometimes cooperate in order to implement the entire standard.
What you're asking depends on the compiler. I think you would have to have special knowledge of the compiler in order to decide this. In the specific case of GCC, it defines a macro to tell you. Search this node of the manual for __GCC_IEC_559.
Well... I don't know the answer to this one :-). The original post seems to indicate that, yes, GCC might define __GCC_IEC_559 if it intends to implement IEEE 754, even if it does not actually do so.
Previously I was receiving warnings from gcc -std=c99 that usleep() was implicitly declared. Then I stumbled across this stackoverflow post, which led me to use -D_BSD_SOURCE. However, now gcc tells me that -D_BSD_SOURCE has been deprecated and I should use -D_DEFAULT_SOURCE instead.
#warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"
Why is -D_BSD_SOURCE deprecated? Why is -D_DEFAULT_SOURCE used instead? And what does it do?
I did some googling, and the results are just filled with people using it to shut gcc up. I couldn't find out why -D_BSD_SOURCE has been deprecated, just that it is.
The glibc manual describes each feature test macro (FTM) including _DEFAULT_SOURCE:
If you define this macro, most features are included apart from
X/Open, LFS and GNU extensions: the effect is to enable features from
the 2008 edition of POSIX, as well as certain BSD and SVID features
without a separate feature test macro to control them. Defining this
macro, on its own and without using compiler options such as -ansi or
-std=c99, has the same effect as not defining any feature test macros; defining it together with other feature test macros, or when options
such as -ansi are used, enables those features even when the other
options would otherwise cause them to be disabled.
This LWN.net article about FTMs provides us with a rationale (among other perhaps interesting info):
The original intent seems to have been that, within each of the glibc
header files that employs FTMs, only one of the __USE_* internal
macros should govern the exposure of any particular definition.
Additionally, the macros should not be used in nested #ifdef
directives. An inspection of the glibc header files quickly shows that
the reality is far from the intent, a situation that led Roland
McGrath to suggest that it was time for a major cleanup to bring
things back to the intended situation. Roland thought that task could
be simplified by eliminating the _BSD_SOURCE and _SVID_SOURCE FTMs,
which, although they had a purpose historically, have ceased to be
useful these days. Anymore, he said, the only macros that are needed
for modern source code are those that relate to formal standards plus
_GNU_SOURCE.
Joseph Myers duly obliged with a series of patches to implement the
first steps in this work. The conservative approach encouraged by
Roland meant that the deprecation of the _BSD_SOURCE and
_SVID_SOURCE FTMs is taking place across two glibc versions. Version
2.19 of glibc added a new FTM, _DEFAULT_SOURCE. Defining this macro causes the default definitions to be exposed even when the explicit
definition of other macros would cause that not to happen. The effect
of defining this macro is equivalent to the effect of explicitly
defining three macros in earlier glibc versions:
cc -D_BSD_SOURCE -D_SVID_SOURCE -D_POSIX_C_SOURCE=200809C
So if you need to define _BSD_SOURCE or _SVID_SOURCE, simply define _DEFAULT_SOURCE too. glibc versions <= 2.18 don't care about it and versions >= 2.19 don't warn if both or all three are defined.
i need portability beyond linux and beyond glibc, and i dislike #ifdef's. so:
/* asprintf() does not appear on linux without this */
#define _GNU_SOURCE
/* gettimeofday() does not appear on linux without this. */
#define _BSD_SOURCE
/* modern glibc will complain about the above if it doesn't see this. */
#define _DEFAULT_SOURCE
I got this book "Beginning C" by Ivor Horton and I'm half way through it and I like it; so far so good. I use Code::Blocks on Windows as my IDE, and now I've run into the problem I cannot solve for about 3 days now.
The author mentions some "optional" functions in <string.h>, like strnlen_s(), and also says that these are available in the new standard — C11 (the book is from 2013; I don't know how new C11 actually is), and he also gives a piece of code that will determine "whether the standard library that comes with your C compiler supports these optional functions".
This is the code:
#include <stdio.h>
int main(void)
{
#if defined __STDC_LIB_EXT1__
printf("Optional functions are defined.\n");
#else
printf("Optional functions are not defined.\n");
#endif
return 0;
}
So I run the code to check if GCC in Code::Blocks does and determine that it doesn't. The book didn't recommend the compiler nor the IDE; I picked up Code::Blocks with GCC on my own, since that's what I do my exams in at college, so I figured I should get familiar with the environment.
The thing is, I have no idea how to "fix" this, since strnlen() doesn't work, strnlen_s() doesn't work, and bunch of others, and I can't really continue through a book. Not that I need them, or that I can't do it any other way (strlen() works just fine) but it would be nice to know how to use non-standard functions.
Up to date versions of GCC certainly do support C11, you need to enable it with the compiler flag -std=c11.
I presume you're using some flavour of MinGW with Code::Blocks - I recommend using MinGW-W64 as it is actively maintained and very up to date.
Also, bundled toolchains of MinGW-W64's gcc are available at TDM-GCC.
The Code::Blocks IDE itself doesn't care which version of C you're using, that doesn't affect what libraries you have available.
You are speaking of the optional Annex K Microsoft pushed through.
K.2 Scope
1 This annex specifies a series of optional extensions that can be useful in the mitigation of
security vulnerabilities in programs, and comprise new functions, macros, and types
declared or defined in existing standard headers.
2 An implementation that defines __STDC_LIB_EXT1__ shall conform to the
specifications in this annex.380)
3 Subclause K.3 should be read as if it were merged into the parallel structure of named
subclauses of clause 7.
It is generally seen as deeply flawed, and Microsoft trying to force it's use as a severe nuisance.
That's especially the case as they are the only major player implementing them, and their versions are non-conformant.
glibc with gcc for example provide most supposed advantages of that annex without introducing new functions, discouraging use of half the standard-library and forcing such a cumbersome API on programmers.
You might want to read the C tag-wiki, and especially grab a draft of the C11 standard (which is from 2011, as the name should imply).
The optional Annex K from the C11 Standard is not widely adopted yet (see Deduplicator's comment below). For instance as of February 2015 it hasn't been merged into glibc.
The good news is that you might try an alternative compiler. For instance Pelles C for Windows is a modified LCC with enhanced support for newest C11 features (like atomics and C11 threads model, that I believe are also mentioned in your book). Here is some basic program, that compiles and runs in it:
#include <stdio.h>
#include <string.h>
int main(void)
{
#if defined __STDC_LIB_EXT1__
printf("Optional functions are defined.\n");
#else
printf("Optional functions are not defined.\n");
#endif
char *str = "Hello Annex K";
printf("%zu\n", strnlen_s(str, 5));
return 0;
}
Output is:
Optional functions are defined.
5
Press any key to continue...
with MVS2008, this line works fine:
_fsopen(file_name, "wb+", _SH_DENYRW);
Borland C++builderX from 2003 complains about the argument _SH_DENYRW. I changed to
_fsopen(file_name, "wb+", SH_DENYRW);
removing the underscore and Borland compiles well now. Is it good what I'm doing? I saw this modification somewhere on the web.
Thanks a lot..
Microsoft has been working bit by bit over time to make the names used in their C/C++ headers and libraries more standards compliant (though they aren't necessarily doing the same for names in the SDK headers and libraries - a subtle but important distinction). So you'll find that more and more of names that aren't in the standard are being prefixed with an underscore.
But MS often provides the ability to use the old, non-standards compliant names for backwards compatibility. You should be able to use the SH_DENYRW name in either MSVC or Borland unless you're telling the compiler to use strict standards compliance (for example, with the /Za option), since MSVC defines the following in share.h:
#if !__STDC__
/* Non-ANSI names for compatibility */
#define SH_DENYRW _SH_DENYRW
#define SH_DENYWR _SH_DENYWR
#define SH_DENYRD _SH_DENYRD
#define SH_DENYNO _SH_DENYNO
#endif
#endif /* _INC_SHARE */