我遇到了一个小问题:
while (read(dp->fd, (char *) &dirbuf, sizeof(dirbuf)) == sizeof(dirbuf)) { ... }
其中dirbuf是:
struct direct dirbuf {
ino_t d_ino; char d_name[DIRSIZ];
};
C如何知道将数据连续读入我们的结构?使用read()Like,我们的dirbuf的对齐非常适合作为字符数组?因为read接受一个void *作为它的第二个参数,将一个结构作为一个转换传递给char *对我来说没什么意义,它如何正确地迎合其他成员元素?
我不确定我是否正确地问这个问题,我希望有人可以解决我的精神错乱背后的问题并帮助我。
感谢。
答案 0 :(得分:6)
将缓冲区转换为char *
是一种经常看到的遗留代码模式。它经常被使用,以至于在它不再需要之后很久就会被输入。
有一点没有void
类型,因此像read(2)
这样的API会将缓冲区参数声明为char *
,并且所有调用者都会将其数据转换为 char *
。
但是read(2)
已经很长很长时间了void *
。很长一段时间以来,必须在通话现场进行任何类型的演员表。
然而,旧代码仍然存在,人们仍在阅读它,然后它们使设计模式永久化。
它没有任何伤害。
关于连续数据,正在发生两件事之一。数据结构和类型被设计为在大多数或所有可能的机器上密集布局,或者首先使用类似的语句将数据写出来,因此填充字节无关紧要,除非要移动数据文件在不同的架构之间。
答案 1 :(得分:3)
它不会读取并正确对齐结构中的字段。它只需要结构的总大小(来自sizeof
)和起始地址(来自&dirbuf
)并读入该内存而不考虑结构声明。
假设文件中的任何内容已经正确对齐以适应结构。
(char *)
演员阵容就是关闭编译器。 (void *)
也会做得很好。或者根本没有强制转换,因为编译器会将指针类型转换为void *而不进行强制转换。
答案 2 :(得分:0)
这必须是对C语言的古老版本的点头,它没有void *
类型而是使用char *
代替。如果你使用的是非古老的编译器并且参数确实是void *
,则不需要向char *
投射任何东西(并且不需要向void *
投射任何东西)
read(dp->fd, &dirbuf, sizeof(dirbuf))
C不知道,也不需要知道如何将数据读入您的特定结构。当您执行上述操作时,文件中的二进制数据将被盲目读入dirbuf
对象占用的原始内存中。如果该二进制数据的布局是正确的(例如,如果文件是通过以相同的方式编写相同的结构来创建的),那么一切都将正确对齐,一切都将自动落入适当的位置。
请注意,除非您正在使用非常严格的规范所涵盖的内容,否则这种直接的二进制写/读技术只能在同一程序的单个会话中使用,或者可能在同一版本的不同会话之间使用在同一平台上的程序。一旦您开始在同一平台上处理不同平台和/或不同版本的代码,一旦数据的原始内存布局发生变化,事情就会轻易崩溃。