14

I noticed M_PI is unavailable on c11. By looking at /usr/include/math.h I can see M_PI is defined if:

#if !defined(__STRICT_ANSI__) || ((_XOPEN_SOURCE - 0) >= 500)
...
#define M_PI 3.1415...
#endif 

Moreover in the math.h from glibc __STRICT_ANSI__ is replaced with __USE_MISC. I am completely lost with this.

What is the story in between --std=c11 and the constants defined in math.h?

Which libc should I consider on a debian distribution ?

By the way, M_PI is defined in c99 and gnu11...

nowox
  • 25,978
  • 39
  • 143
  • 293

3 Answers3

24

It's simple: M_PI is not defined in standard C. Provide your own definition if you want to be standard-compliant.

C compilers cannot introduce such constants without breaking legal C programs (the name is not reserved, and could be used as an identifier), and as such, they are only defined as an extension.

GCC 4.9 when used with -std=c99 doesn't define M_PI, but does when used with -std=gnu99

milleniumbug
  • 15,379
  • 3
  • 47
  • 71
  • It was defined in 'c99' though. – nowox Mar 25 '15 at 19:19
  • 2
    @coin It shouldn't be - C99 also doesn't define `M_PI`. – milleniumbug Mar 25 '15 at 19:21
  • damned, I ignored that I always thought C99 was the default standard for gcc. So what is it then? – nowox Mar 25 '15 at 19:27
  • 1
    The default of GCC is `gnu90`. 5.1.0 (not released yet) will default to `gnu11`. – cremno Mar 25 '15 at 19:28
  • Perhaps one more question. Does `--std=c99` use glibc? If yes, what are the mechanism in gcc that undef `__STRICT_ANSI`? – nowox Mar 25 '15 at 19:58
  • 1
    @coin: It uses the same libc as with different or without `-std` options (which usually is glibc, but doesn't have to be. E.g. on Windows). Also read http://man7.org/linux/man-pages/man7/feature_test_macros.7.html and https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html for more information. – cremno Mar 25 '15 at 20:07
  • 3
    @coin Why bother? Either you want more stuff, then you use `-std=gnu99` with extensions, or you don't want extensions because you want portability and don't want to accidentally limit yourself to a single compiler, in that case you use `-std=c99`. – milleniumbug Mar 25 '15 at 20:17
8

If you just want M_PI while looking for a more comprehensive answer with POSIX / XOPEN feature tests macros, etc., an interim solution is:

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

That's "1.20" format, which is also sufficient for 'round-trip' representation for an 80 bit extended type. double precision is "1.16". For 128-bit quad precision:

#define M_PI (3.14159265358979323846264338327950288)

The "1.35" format for round-trip precision. This means if you want to print out a floating point double, and recover the same value when you read it back, you should use "%+1.16" for printf functions, as so on. You might say that a double doesn't have 17 significant digits, but those digits are not 'junk' if you want to recover a value.

Anyway - there are better resources than this available.

Brett Hale
  • 21,653
  • 2
  • 61
  • 90
  • For correct 1.16 --> +1. BTW: See any downside to having lots of PI digits like 80 digits? – chux - Reinstate Monica Mar 25 '15 at 20:39
  • 1
    @chux - not that I can think of. gcc at least includes the gmp / mpfr / mpc libraries to take care of all multiple-precision issues, with correct (and selectable) rounding modes, etc. If an 80 digit PI value was assigned to a single precision float, I would expect it to do the right thing. Don't know how up to date [this](https://gcc.gnu.org/wiki/FloatingPointMath) page is. I don't know clang's approach. – Brett Hale Mar 25 '15 at 21:08
3

The M_PI macro isn't defined by the C11 standard: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf

Therefore, the #if guards are protecting you from problems in case you want to define your own M_PI macro. gcc is doing exactly the right thing. The standard headers shouldn't arbitrarily define macros that are not in the standard.

juhist
  • 4,210
  • 16
  • 33