有人能解释一下“dirent”的定义吗? Solaris 中的结构?
最近,我正在研究“dirent”结构(在 dirent.h 中),对其定义有点困惑。
注意:此头文件来自我学校的 Solaris 计算机。
typedef struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[1];
} dirent_t;
特别是 d_name 字段。 这在操作系统中如何工作? 如果您需要存储以空字符结尾的字符串,那么单个字符的数组有什么用呢? 我知道您可以通过数组的第一个元素获取数组的地址,但我仍然很困惑。 显然有些事情正在发生,但我不知道是什么。 在我家里的 Fedora Linux 系统上,这个字段被简单地定义为:
char d_name[256];
现在,由于显而易见的原因,这变得更有意义了。 有人可以解释为什么 Solaris 头文件这样定义结构吗?
Recently I was looking at the 'dirent' structure (in dirent.h) and was a little puzzled by its definition.
NOTE: This header file is from a Solaris machine at my school.
typedef struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[1];
} dirent_t;
Particularly the d_name field. How would this work in the operating system? If you need to store a null terminated string what good is an array of a single char? I know that you can get the address of an array by its first element but I am still confused. Obviously something is happening, but I don't know what. On my Fedora Linux system at home this field is simply defined as:
char d_name[256];
Now that makes a lot more sense for obvious reasons. Can someone explain why the Solaris header file defines the struct as it does?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如其他人指出的那样,结构体的最后一个成员没有任何设置的大小。 无论数组有多长,实现都会决定它需要容纳要放入其中的字符。 它通过动态地为结构分配内存来实现这一点,例如使用
malloc
。不过,将成员声明为大小 1 很方便,因为很容易确定任何
dirent
变量d
占用了多少内存:使用大小 1 也会阻止接收者此类结构体值试图在其中存储自己的名称而不是分配自己的
dirent
值。 使用 Linux 定义,可以合理地假设您拥有的任何dirent
值都将接受 255 个字符的字符串,但 Solaris 不保证其dirent
值将存储更多比他们需要的字符。我认为是 C 99 为结构体的最后一个成员引入了特殊情况。 该结构可以这样声明:
该数组没有声明的大小。 这称为灵活数组成员。 它完成了与 Solaris 版本相同的事情,只是不存在结构本身可以保存任何名称的幻想。 通过查看它,您就知道还有更多内容。
使用“灵活”声明,占用的内存量将如下调整:
这是因为灵活数组成员不考虑结构的大小。
您不经常看到这样的灵活声明的原因,尤其是在操作系统库代码中,可能是为了与不支持该功能的旧编译器兼容。 它还为了与针对当前定义编写的代码兼容,如果结构的大小发生这样的变化,该代码就会中断。
As others have pointed out, the last member of the struct doesn't have any set size. The array is however long the implementation decides it needs to be to accommodate the characters it wants to put in it. It does this by dynamically allocating the memory for the struct, such as with
malloc
.It's convenient to declare the member as having size 1, though, because it's easy to determine how much memory is occupied by any
dirent
variabled
:Using size 1 also discourages the recipient of such struct values from trying to store their own names in it instead of allocating their own
dirent
values. Using the Linux definition, it's reasonable to assume that anydirent
value you have will acept a 255-character string, but Solaris makes no guarantee that itsdirent
values will store any more characters than they need to.I think it was C 99 that introduced a special case for the last member of a struct. The struct could be declared like this instead:
The array has no declared size. This is known as the flexible array member. It accomplishes the same thing as the Solaris version, except that there's no illusion that the struct by itself could hold any name. You know by looking at it that there's more to it.
Using the "flexible" declaration, the amount of memory occupied would be adjusted like so:
That's because the flexible array member does not factor in to the size of the struct.
The reason you don't see flexible declarations like that more often, especially in OS library code, is likely for the sake of compatibility with older compilers that don't support that facility. It's also for compatibility with code written to target the current definition, which would break if the size of the struct changed like that.
在内存中,dirent 结构后面会紧跟一个包含名称其余部分的内存块,并且可以通过 d_name 字段访问该内存。
The dirent struct will be immediately followed in memory by a block of memory that contains the rest of the name, and that memory is accessible through the d_name field.
这是 C 中使用的一种模式,用于指示结构末尾的任意长度数组。 C 中的数组没有内置的边界检查,因此当您的代码尝试访问从 d_name 开始的字符串时,它将继续越过结构的末尾。 这依赖于
readdir()
将分配足够的内存来保存整个字符串加上终止 nul。This is a pattern used in C to indicate an arbitrary-length array at the end of a structure. Arrays in C have no built-in bounds checking, so when your code tries to access the string starting at d_name, it will continue past the end of the structure. This relies on
readdir()
will allocate enough memory to hold the entire string plus the terminating nul.对我来说这看起来像是一个微观优化。 名称通常很短,所以为什么要分配您知道会不会被使用的空间呢? 此外,Solaris 可能支持长度超过 255 个字符的名称。 要使用这样的结构,您只需分配所需的空间并忽略假定的数组大小。
It looks like a micro-optimization to me. Names are commonly short, so why allocate space that you know will go unused. Also, Solaris may support names longer than 255 characters. To use such a struct you just allocate the needed space and ignore the supposed array size.