6

When we include <dirent.h> and <limits.h> to a c file, dirent structs' d_name variable shows We must not include limits.h! in the variable description in the ide. When I look at the file /usr/include/x86_64-linux-gnu/bits/dirent.h it contains the following code piece.

...
struct dirent
  {
#ifndef __USE_FILE_OFFSET64
    __ino_t d_ino;
    __off_t d_off;
#else
    __ino64_t d_ino;
    __off64_t d_off;
#endif
    unsigned short int d_reclen;
    unsigned char d_type;
    char d_name[256];       /* We must not include limits.h! */
  };
...

My question is why we must not include limits.h. I've searched online, but I couldn't find any satisfying answer.

sipihr
  • 148
  • 6

3 Answers3

5

Each standard header has a specification for what it exposes or may expose. dirent.h exposes struct dirent, DIR, and the relevant functions, and reserves names starting with d_. Some headers are also permitted but not required to expose things exposed by certain other headers; dirent.h is not one of these. So indirectly including limits.h would be a violation of the namespace and would break conforming programs that assume they can use names that limits.h would expose for their own identifiers.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 2
    This sounds plausible, but do you have any reference for these claims? – Ctx Oct 16 '19 at 20:46
  • 1
    probably because there's a max file name len in limits.h – Jean-François Fabre Oct 16 '19 at 20:48
  • 1
    I checked limits.h and included files and could not find a max filename len, though. But maybe it's somewhere and I didn't find it. – Jean-François Fabre Oct 16 '19 at 20:54
  • @Jean-FrançoisFabre If you are using linux there is NAME_MAX in /usr/include/linux/limits.h NAME_MAX, but probably not cross-platform. – unlut Oct 16 '19 at 20:55
  • that would explain a lot. And anyway, the programmers _know_ that the limit is 256. They just have to adapt it if the value changes in limits.h. After all a set of include files is a coherent whole. Maintanability issues aren't the priority – Jean-François Fabre Oct 16 '19 at 20:56
  • I think I finally understand what you mean, but can you show an example why would you want to use same name with a standard definition in your own definition? – unlut Oct 16 '19 at 21:12
  • @unlut `NAME_MAX` is not guaranteed to be defined. [Per POSIX ``](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html): "A definition of one of the values **shall be omitted** from the `` header on specific implementations where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. ... `NAME_MAX`..." – Andrew Henle Oct 16 '19 at 21:14
  • @AndrewHenle Your quote does not explain why I can't include limits.h in dirent.h, or if does but I didn't understand can you explain? – unlut Oct 16 '19 at 21:21
  • 3
    @unlut: Why it can't is covered here: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02 – R.. GitHub STOP HELPING ICE Oct 16 '19 at 21:22
  • @unlut If `NAME_MAX` can't be guaranteed to be defined, there's no point in including `limits.h`. – Andrew Henle Oct 16 '19 at 21:22
  • @AndrewHenle If NAME_MAX if defined you can use it, and if its not you can fall back to magic number 256. – unlut Oct 16 '19 at 21:24
  • @unlut Well, as Linux supports filesystems with different maximum pathname lengths, `NAME_MAX` being defined would be a defect that shouldn't be counted on. Again - no point. – Andrew Henle Oct 16 '19 at 21:27
  • @R.. Thank you for the reference, does C standard also guarantee this or is this just a POSIX thing? – unlut Oct 16 '19 at 21:29
  • @unlut `NAME_MAX` does not exist in the C standard. – Andrew Henle Oct 16 '19 at 21:32
  • @AndrewHenle I am not asking whether NAME_MAX is defined or not, but whether including a C header file must not define something reserved that belongs to another C header file. – unlut Oct 16 '19 at 21:35
  • @R.. I accepted this answer as correct. I am using VS Code as IDE. When I include only `dirent.h`, the helping window shows only the details of `d_name` when I hover the mouse on it. But when I also include `limits.h`, it shows `We must not include limits.h!` comment. I thought there is a header conflict and I shouldn't include `limits.h`. Now I understand why. I have never thought VS Code is that smart. Thank you. – sipihr Oct 16 '19 at 21:56
1

The maximum number of characters in a file name (component) is NAME_MAX. The number 256 equals NAME_MAX + 1 (or is the maximum of that on any targeted system). Naturally using a bare magic number like this is generally frowned upon.

But that macro is defined only in <limits.h>. It cannot be included in <dirent.h> because the latter is not supposed to define any of these macros.

  • And as I noted above, POSIX specifies that `NAME_MAX` shall not be defined should there not be a fixed maximum file name length. And Linux supports filesystems that have different filename lengths... – Andrew Henle Oct 16 '19 at 21:16
1

Additionally, values such as NAME_MAX may not be guaranteed to be defined.

Per POSIX <limits.h>(bolding mine):

The values in the following list may be constants within an implementation or may vary from one pathname to another. For example, file systems or directories may have different characteristics.

A definition of one of the values shall be omitted from the <limits.h> header on specific implementations where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. The actual value supported for a specific pathname shall be provided by the pathconf() function.

...

{PATH_MAX}

Maximum number of bytes in a pathname, including the terminating null character.

Minimum Acceptable Value: {_POSIX_PATH_MAX}

Minimum Acceptable Value: {_XOPEN_PATH_MAX}

As noted in the comments, Linux supports filesystems with different maximum pathname lengths.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56