Search code examples
clanguage-lawyerheader-filesc-standard-library

Why stdio.h, stdlib.h, string.h declare size_t, NULL, etc. instead of #include <stddef.h>?


The headers stdio.h, stdlib.h, string.h declare size_t, NULL, etc.

Why declaring size_t, NULL, etc. instead of #include <stddef.h>?


Solution

  • Why declaring size_t, NULL, etc. instead of #include <stddef.h>?

    Per C17 7.19/3, stddef.h does define NULL, so the question is unfounded. Inasmuch as the premise seems to be in part that the role served by stddef.h makes it a good place for NULL to be defined, the standard committee seems to agree.

    stdio.h (7.21.1/2), stdlib.h (7.22/3), and string.h (7.24.1/1) also define NULL. As to why this is, I am inclined to say that a combination of historical variation in which headers defined which macros plays a part, but it is also the case that each of these headers declare at least one function whose arguments and / or return value attribute specific significance to null pointers. For example, fopen() returns a null pointer when it fails. Although it is not essential to use the macro NULL to represent a null pointer constant, it is highly idiomatic, so ensuring that these headers define it makes it accessible in at least most of the standard library cases where it will be wanted, without requiring inclusion of a header just for that purpose.

    Similar applies for size_t, less the historical variation angle.

    Addendum

    Upon review, I think I initially misread the question. However, to the extent that it inquires about why the spec says that stdio.h etc. define various identifiers that are also defined by stddef.h, when it could instead specify that those headers #include <stddef.h>, I think it still largely comes down to each header providing all the declarations it needs, so as to stand substantially on its own.

    Additionally, however, if the spec said (for example) that string.h included stddef.h then that would make all identifiers specified to be declared by the latter reserved (in various senses) in any translation unit that includes the former, pursuant to section 7.1.3 of the spec. By instead specifying that particular identifiers are declared or defined in string.h, only those specific identifiers are reserved by inclusion of string.h.