Aside from the NAN macro, C99 has two ways to generate a NaN value for a floating point number, the nanf(const char *tagp)
function and strtof("NAN(char-sequence)")
.
Both of these methods of generating a NaN take an optional string argument (*tagp in nanf()
and the char-sequence in the strtof method). What exactly does this string argument do? I haven't been able to find any concrete examples of how you'd use it. From cppreference.com we have:
The call nan("string") is equivalent to the call strtod("NAN(string)", (char**)NULL);
The call nan("") is equivalent to the call strtod("NAN()", (char**)NULL);
The call nan(NULL) is equivalent to the call strtod("NAN", (char**)NULL);
And nan(3) says:
These functions return a representation (determined by tagp) of a quiet NaN. [snip]
The argument tagp is used in an unspecified manner. On IEEE 754 systems, there are many representations of NaN, and
tagp selects one.
This doesn't really tell me what I can use for the tagp string or why I'd ever want to use it. Is there a list anywhere of the valid options for this tag string, and what would the reason be to use one over the default nanf(NULL)
?
Tl;Dr : tagp
argument gives you the ability to have different NAN values.
This is from man page for nan(3) which gives a little more information on tagp
.
Mainly:
The nan() functions return a quiet NaN, whose trailing fraction field
contains the result of converting
tagp to an unsigned integer.
This gives you the ability to have different NAN values.
Specifically from the C99 Rationale doc:
Other applications of NaNs may prove useful. Available parts of NaNs
have been used to encode auxiliary information, for example about the
NaN’s origin. Signaling NaNs might be candidates for filling
uninitialized storage; and their available parts could distinguish
uninitialized floating objects. IEC 60559 signaling NaNs and trap
handlers potentially provide hooks for maintaining diagnostic
information or for implementing special arithmetics.
There is an implementation of it here. Mind you, this may or may not be standard conforming, as noted in comments. However, it should give you an idea of what tagp
is used for.
As in the man page, you can see the replacement mentioned above:
nan("1") = nan (7ff8000000000001)
nan("2") = nan (7ff8000000000002)
Full man page here:
NAN(3) BSD Library Functions Manual
NAN(3)
NAME
nan -- generate a quiet NaN
SYNOPSIS
#include
double
nan(const char *tagp);
long double
nanl(const char *tagp);
float
nanf(const char *tagp);
DESCRIPTION
The nan() functions return a quiet NaN, whose trailing fraction field contains the result of converting
tagp to an unsigned integer. If tagp is too large to be contained in the trailing fraction field of the
NaN, then the least significant bits of the integer represented by tagp are used.
SPECIAL VALUES
If tagp contains any non-numeric characters, the function returns a NaN whos trailing fraction field is
zero.
If tagp is empty, the function returns a NaN whos trailing fraction field is zero.
STANDARDS
The nan() functions conform to ISO/IEC 9899:2011.
BSD July 01, 2008
This doesn't really tell me what I can use for the tagp string or why I'd ever want to use it.
Some floating point standards, e.g., IEEE-754, have multiple different NaN values. This nan
function specification allows an implementation to select a specific NaN representation depending on the string on a way that might be specified by the implementation.