Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有人能解释一下';dirent';Solaris中的结构?_C_Unix_Struct_Solaris - Fatal编程技术网

C 有人能解释一下';dirent';Solaris中的结构?

C 有人能解释一下';dirent';Solaris中的结构?,c,unix,struct,solaris,C,Unix,Struct,Solaris,最近我在看“dirent”结构(在dirent.h中),对它的定义有点困惑 注意:此头文件来自我学校的Solaris计算机 因为显而易见的原因,这就更有意义了。有人能解释一下为什么Solaris头文件定义了struct吗?dirent struct将在内存中紧接着一个包含名称其余部分的内存块,并且可以通过d_name字段访问内存。这是C中使用的一种模式,用于指示结构末尾的任意长度数组。C中的数组没有内置的边界检查,因此当代码尝试访问从d_name开始的字符串时,它将继续访问到结构的末尾。这取决

最近我在看“dirent”结构(在dirent.h中),对它的定义有点困惑

注意:此头文件来自我学校的Solaris计算机


因为显而易见的原因,这就更有意义了。有人能解释一下为什么Solaris头文件定义了struct吗?

dirent struct将在内存中紧接着一个包含名称其余部分的内存块,并且可以通过d_name字段访问内存。

这是C中使用的一种模式,用于指示结构末尾的任意长度数组。C中的数组没有内置的边界检查,因此当代码尝试访问从d_name开始的字符串时,它将继续访问到结构的末尾。这取决于
readdir()
将分配足够的内存来保存整个字符串和终止nul。

我觉得这是一个微型优化。名称通常很短,所以为什么要分配您知道将不使用的空间呢。此外,Solaris可能支持长度超过255个字符的名称。要使用这样的结构,只需分配所需的空间并忽略假定的数组大小。

正如其他人所指出的,结构的最后一个成员没有任何设置大小。无论实现决定数组需要多长,该数组都可以容纳要放入其中的字符。它通过为结构动态分配内存来实现这一点,例如使用
malloc

不过,将成员声明为大小为1很方便,因为很容易确定任何
dirent
变量
d
占用了多少内存:

sizeof(dirent) + strlen(d.d_name)
使用大小1也会阻止此类结构值的接收者尝试在其中存储自己的名称,而不是分配自己的
dirent
值。使用Linux定义,可以合理地假设您拥有的任何
dirent
值都将接受255个字符的字符串,但Solaris不能保证其
dirent
值将存储比需要更多的字符

我认为是C99为结构的最后一个成员引入了一个特例。结构可以这样声明:

typedef struct dirent {
  ino_t d_ino;
  off_t d_off;
  unsigned short d_reclen;
  char d_name[];
} dirent_t;
数组没有声明的大小。这就是所谓的灵活数组成员。它实现了与Solaris版本相同的功能,只是不存在结构本身可以保存任何名称的错觉。通过观察,你知道事情还有很多

使用“flexible”声明,占用的内存量将调整如下:

sizeof(dirent) + strlen(d.d_name) + 1
这是因为灵活的数组成员不考虑结构的大小


您不经常看到这种灵活声明的原因,特别是在OS库代码中,可能是为了与不支持该功能的旧编译器兼容。这也是为了与针对当前定义编写的代码兼容,如果结构的大小像这样更改,则会中断定义。

为什么不在结构中使用指针呢?为了节省几个字节?我想在操作系统层面上可能是这样的。指针做的事情不一样。使用指针需要多个内存分配——一个用于dirent结构,一个用于名称,dirent指向名称。使用单字节数组模式意味着一次分配,其中d_name是名称的第一个字节。明白了。感谢您的澄清,我没有考虑需要额外的分配。实际上,条目d_recen包含此结构实例的实际大小,您不必自己计算。啊,您是对的。不过,分配结构的人仍然需要计算出要分配多少,因此有一个简单的方法来计算它还是很好的。我在为我的爱好操作系统实现自己的ext2驱动程序时回到了这个问题。对我来说,关键是我使用这种结构的方式。我从磁盘读取目录条目,然后将缓冲区转换为
目录。然后,灵活数组成员对应于文件名字符。然后只需读取从d.name开始的
name\u len
字符即可。实际上,它在实践中非常有效。您可能需要了解rec_len是如何使用的,以了解它为什么有意义。
typedef struct dirent {
  ino_t d_ino;
  off_t d_off;
  unsigned short d_reclen;
  char d_name[];
} dirent_t;
sizeof(dirent) + strlen(d.d_name) + 1