2015-03-25 72 views
8

Zauważyłem, że M_PI jest niedostępne na c11. Patrząc na /usr/include/math.h widzę M_PI jest zdefiniowane, gdy:M_PI nie jest dostępny z gcc --std = c11, ale z --std = gnu11?

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

Ponadto w math.h z glibc__STRICT_ANSI__ otrzymuje z __USE_MISC. Jestem całkowicie zagubiony z tym.

Jaka jest historia między --std=c11 a stałymi określonymi w math.h?

Którego libc należy wziąć pod uwagę przy dystrybucji debian?

Nawiasem mówiąc, M_PI jest zdefiniowana w c99 i gnu11 ...

+0

Dlaczego masz tag C++ 11, jeśli o to pytasz wyraźnie chodzi o C11, a nie C++ 11? – juhist

+2

Tak, istnieje, a Twój wpis był już edytowany, aby mieć tag c11 zamiast C++ 11. – juhist

Odpowiedz

11

To proste: M_PI nie jest zdefiniowane w standardzie C podać własną definicję, jeśli chcesz być zgodny ze standardami.

Kompilatory C nie mogą wprowadzić takich stałych bez łamania legalnych programów C (nazwa nie jest zarezerwowana i może być używana jako identyfikator) i jako takie są one zdefiniowane tylko jako rozszerzenie.

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

+0

Jednak został zdefiniowany w 'c99'. – nowox

+2

@coin To nie powinno być - C99 również nie definiuje 'M_PI'. – milleniumbug

+0

Cholera, zignorowałem, że zawsze uważałem C99 za domyślny standard dla gcc. Więc co to jest? – nowox

3

M_PI makro nie jest zdefiniowane przez standard C11: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf

Dlatego #if strażnicy chronią Cię przed problemami w przypadku, gdy chcesz zdefiniować własne M_PI makro. gcc robi dokładnie to, co należy. Standardowe nagłówki nie powinny arbitralnie definiować makr, które nie są w standardzie.

4

Jeśli chcesz tylko M_PI patrząc na bardziej wyczerpującą odpowiedź z testami funkcji POSIX/XOPEN makr itp rozwiązanie tymczasowe jest:

#ifndef M_PI 
#define M_PI (3.14159265358979323846) 
#endif 

To Format „1.20”, który jest również wystarczająca dla reprezentacja "w obie strony" dla typu rozszerzonego o 80 bitów. podwójna precyzja to "1,16". Dla 128-bitową precyzją quad:

#define M_PI (3.14159265358979323846264338327950288) 

formacie "1,35" dla precyzji w obie strony. Oznacza to, że jeśli chcesz wydrukować zmiennoprzecinkowe podwójne i odzyskać tę samą wartość podczas odczytu, powinieneś użyć "% + 1.16" dla funkcji printf, jak i tak. Możesz powiedzieć, że double nie ma 17 cyfr znaczących, ale te cyfry nie są "śmieciami", jeśli chcesz odzyskać wartość.

W każdym razie - są lepsze zasoby niż ta available.

+0

Poprawnie 1.16 -> +1. BTW: Widzisz jakąkolwiek wadę posiadania wielu cyfr PI, takich jak 80 cyfr? – chux

+1

@chux - nie, że mogę myśleć. gcc przynajmniej zawiera biblioteki gmp/mpfr/mpc, aby zająć się wszystkimi problemami z wieloma precyzją, z właściwymi (i wybieranymi) trybami zaokrąglania itp. Jeśli 80-bitowa wartość PI została przypisana do pojedynczej precyzji, spodziewam się, że robić to, co trzeba. Nie wiem, jak aktualna jest ta strona (https://gcc.gnu.org/wiki/FloatingPointMath). Nie znam podejścia klangowego. –