tags:

views:

177

answers:

5

I'm wondering what would be the best way to store math constants that are used throughout an entire program?

#define PI 3.14159265
#define SPEEDOFLIGHT 2.99792458e8

or

enum constants { PI = 3.14159265; SPEEDOFLIGHT = 2.99792458e8; }

Thanks

+12  A: 

None of them, use constant values to preserve compiler's type checking:

static const double PI = 3.14159265;
static const double SPEEDOFLIGHT = 2.99792458e8; 
  • The #define is text replacement only and type unaware.
  • Enums are not suited for all types. I am not sure but I think not even for double values.

EDIT: thanks aaa. I forgot the static keyword, specially useful when the constants are declared in c headers. (In C++ the static is not needed)

jdehaan
probably should make them static to avoid linker errors
aaa
static const double it is then, thanks guys!
Alex Marcotte
This is very bad advice. For instance, you won't be able to use expressions involving `PI` as initializers for static data.
R..
Agree with R. **You can't even initalize another const with a const in C.**
Luther Blissett
This here is really an answer in terms of C++. Since the question is tagged C, it is not appropriate.
Jens Gustedt
+1  A: 

Since enum's are integer constants, I would go with #define.

I agree with jdehaan that global const objects are even better.

schot
Kudos for being the only answer to explicitly mention that `enum` is only for integer types, but I disagree that global `const` objects are better (at least not without mentioning their limitations).
jamesdlin
+1  A: 

Agree with jdehaan, prefer constants to do more explicit type checking/conversion.

In addition, using an enum like you described isn't really the purpose of an enum. Those constants are only mathematically related (if cosmologist hocus-pocus ends up being correct). The purpose of an enum is to combine like values, such as:

enum color
{
  red = 0xFF0000;
  yellow = 0xFFFF00;
  baby_puke_green = 0x9ACD32;
}
Merlyn Morgan-Graham
+5  A: 

Personally i prefer to just make pi and c = 1 and let the universe deal with the problem

Martin Beckett
Or normalize :)
Nathan Fellman
+9  A: 

Do not use const variables for this! In the C language, a const qualified variable is not a constant in the sense of constant expression, so it cannot be used in initializing a static/global variable. This has major practical consequences; for instance, the following will not work:

static const double powers_of_pi[] = { 1, PI, PI*PI, PI*PI*PI, PI*PI*PI*PI, };

The proper solution is #define. It's probably best to use the l suffix so that they'll have type long double, and include sufficiently many decimal places that the values will be correct for long double types up to 128-bit. Then you can use them wherever any floating point type is expected; C will silently convert them down to lower precision as needed.

R..
+1: C const are rubbish. For example you can't even do this: `static const double pi=3.1415926; static const double tau=2*pi;` because in C const initializers always have to be compile time constants, which pi isn't.
Luther Blissett
Thanks for the support injecting some sanity into this topic. It seems like everyone else is coming from a C++ background and thinks what works in C++ should work in C... :-(
R..
@Luther, shouldn't call them rubbish. They have their limited use, but certainly not the one somebody that is coming from a C++ background expects. `const` should never have been chosen as the keyword for what it stands, `unmutable` or something like that would have been much saner, for both, C and C++.
Jens Gustedt
Static/global `const` arrays have some usefulness because they serve as a sort of function from the (small) integers to arbitrary data, but I can hardly think of any use for individual `const` variables... The only two that come to mind right off are using their addresses as sentinel pointer values, and exporting constants from a library without their values getting hard-coded into the calling application (which could have shared-library ABI issues).
R..