06-17-2010 12:18 PM
As it turns out, NI has a union for double constants set up in math.h, using a char array and a double:
#ifndef _DBL_CONST_T
#define _DBL_CONST_T
typedef const union {
unsigned char a[8];
double val;
} _DoubleConst_t;
#endif
So, if you set the char array to the NaN bit pattern, then you could reference DoubleConst.val as a NaN literal without making a function call.
So let's see, how can we get all 1's into the char array as an initializer so that the compiler does it at compile time?
_DoubleConst_t dNaN = {'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff'}; ?
Lemme try that ...
Compiles OK ...
int i = IsNotANumber(dNaN.val); yields a '1' (true) so the NaN value is good,
so now, can I use it as an initializer in a top level variable?
dValue = dNaN.val;
NO! Compiler says it's not a constant!!!
Woe is me ...
06-17-2010 12:19 PM - edited 06-17-2010 12:29 PM
The flaw in my thinking is that the initializer executes at run time, not compile time.
So I think there's no way to do it at all, it takes a union to get under the type system in C, and we see that doesn't work without runtime support.
NI would have to modify the compiler to get this going I should think, or maybe the preprocessor.
06-17-2010 12:31 PM
06-18-2010 05:46 AM
On some previous occasions when I had to use constant initialisers for structure fields that were not fully defined until runtime, I added an indirection to the field to get around the problem. So instead of trying:
typedef struct {
int val;
int param;
} structStore;
static int default = 99;
static stuctStore abc = {default, 0};
which doesn't work, you can adjust the code slightly as follows:
typedef struct {
int *val;
int param;
} structStore;
static int default = 99;
static stuctStore abc = {&default, 0};
which does. Maybe you can have a similar approach to your NaNs, by adding an indirection somewhere to get around the constant initialiser problem?
JR
06-18-2010 02:45 PM
Well, I think the compiler may not like the idea of a dereference in the initializer of a top level variable. i.e. that still seems to me like it's a runtime thing.
double myDouble = *(dNaN.val);
I'll try this but I suspect the compiler will complain.
06-18-2010 03:13 PM
Didn't seem to work.
As an aside, as I recall Fortran 77 allows runtime-like syntax in an initializer or a common (i.e. global) variable: you wrote code to express how you wanted things initialized, and it looked just like run-time code, but it was "executed" by the compiler at compile time.
Or maybe this was a Hewlett Packard extension to Fortran 77.
Menchar
06-23-2010 03:42 PM
And here's another thought -
On any of the numeric controls, when you establish the default value for a control with a floating point type, you should be able to select NaN. You can select positive and negative infinity for the max and min values, so why not NaN for the default?
It seems to me good practice to purposely spoil the default value for doubles to NaN so as to distinguish the value from the otherwise benign "0.0" or other legitimate numeric value.
Menchar
06-23-2010 07:53 PM
I'm not sure I understand why the NotANumber() function won't work for you.
I use it all the time, I mostly initialize variables with it to give an indication that the value returned from a function is invalid.
Can you enlighten me as to why you absolutely need a constant?
Perhaps you can do something like this instead?:
const double NaN = NotANumber();
06-23-2010 08:51 PM
Try using NotANumber() to initialize a top level variable.
06-24-2010 02:54 PM
What do you mean by a "top level variable"?
Do you mean a global?