As far as I understood, NAN
can be [assigned] to a double
type variable
That is correct. NaN
is one of the special values defined for IEEE-754-based types like float
and double
.1
but not necessarily to int
/ size_t
Right. NaN
is not a value defined for integral types int
or size_t
.
You can't store NaN
in an integral variable for the same reason you can't store 3.14 in an integral variable. It's just not one of the values that integral types can hold.
(One of the formal definitions of a data type in programming is that it is a set of values, and a set of operations on those values. For types float
and double
— but only for those types — NaN
is one of the values. Actually, there are multiple NaN
values, but that's a different story.)
For the floating-point types, NaN
s are sentinel values, well-defined "not a value" values. Some types have sentinel values, and some don't. For example, for pointer types, NULL
is the sentinel "not a valid pointer" value. In C strings, the null character \0
is a sentinel value marking the end of the string. On the other hand, when you call getchar
, EOF
is the "not a character" value. (This doesn't make EOF
a sentinel value for type char
, though, since EOF
is not a value of type char
.)
But there is no predefined sentinel value for any of the other integral types. The way integers are used in real programs, there's no value that could be reserved as a sentinel that might not also be a valid value.
If you have an integer variable and you need a sentinel value, you will need to define one of your own, if you can. For example, if you know that your values are always positive, you can use -1 as a sentinel value. But this will be, at best, a convention: the value -1 won't be treated specially by the language, or the CPU — it's just another integer value.
It's great that floating-point and pointer types have sentinel values, and it's sometimes a nuisance that other types don't. The ad hoc conventions one has to use when trying to define sentinel values for other types frequently lead to various nuisances. In order for EOF
to work as a sentinel value for getchar
, programmers have to remember to always store getchar
's return value in a variable of type int
, not char
. A function like read
that returns a number of characters read, or -1 to indicate an error, is difficult to define a good return type for, since it has to be signed to accommodate -1, but could otherwise be unsigned.2 The function mktime
, which converts a broken-down time structure back to an integral time_t
value, returns -1 for error, meaning you can't unambiguously tell whether you've gotten an error, or have successfully converted the time 23:59:59 on December 31, 1969.
Footnote 1: Types float
and double
aren't necessarily based on the IEEE-754 definitions in C, but on most systems these days, they are.
Footnote 2: I believe that's why read
is defined as returning a value of type ssize_t
, and I believe type ssize_t
is a "signed size_t
", or in other words, "A value that would otherwise be unsigned, just like size_t
is, except it has to be signed so it can return -1".