【问题标题】:initialization of C structure arrayC结构体数组的初始化
【发布时间】:2020-09-03 01:48:20
【问题描述】:

unix 6th 源代码。很老了。

conf.h

 struct bdevsw {
   int (*d_open)();
   int (*d_close)();
   int (*d_strategy)();
   int *d_tab;
 } bdevsw[];

conf.c

 int (*bdevsw[])(){
    &nulldev, &nulldev, &rkstrategy, &rktab,
    &nodev, &nodev, &nodev, 0,
    0
 }

我的问题是为什么不初始化,

 bdevsw[] = {......}

【问题讨论】:

  • UnixV6 于 1975 年推出,long 甚至早于 C89。 C 甚至 你当时展示的类型的结构初始化吗? :-)
  • 乍一看,初始化stmt中的第二个括号使它看起来像一个让我感到困惑的函数。
  • 如果这是 K&R 风格的 C,与现代 C 相比,它会非常看起来很古怪。
  • V7 对此进行了一些清理;它有struct bdevsw bdevsw[] = { ... }
  • 关于:struct bdevsw { int (*d_open)(); int (*d_close)(); int (*d_strategy)(); int *d_tab; } bdevsw[]; 不要将数据声明放在头文件中(将数据声明放在 *.c 源文件中,仅将结构类型定义放在头文件中)否则,当此头文件包含在多个源文件中的数据将有多个实例。此外,这声明了一个没有长度值的数组,这在 C 中是不允许的。编译器最多会定义一个指向结构类型的点。

标签: c unix


【解决方案1】:

为此答案收集的所有信息均来自我信任的狮子会评论书副本。这是非常早期 UNIX 代码的一个很好的资源。

如果您将这种怪异的声明注入cdecl,您会发现它的目的是:

bdevsw声明为指向返回int的函数的指针数组。

因此它根本不是代码(a),而是函数的数组定义,每个设备一个,与您的建议几乎相同。

它不在头文件中的原因可能是以下原因。


首先,conf.c 文件实际上是mkconfauto-generated,因为该文件包含给定UNIX 系统的设备详细信息(块和字符设备,保存在bdevswcdevsw 中) .

作为一个自动生成的文件,将数据类型的声明(在不同系统之间保持一致)和数组的定义(每个系统都会改变)分开是有意义的。该文件顶部的注释表明它和low.smkconf 的结果。


其次,有不少 C 文件包含conf.h。例如,bio.c(块 I/O)、sys3.c(文件系统调用)、fio.c(文件调用)和alloc.c(非常早的初始化以读取根超级块)。

所以,如果数组是在头文件中定义的(假设为static以防止重复定义),每个源文件基本上都会有它的自己的副本,浪费宝贵的空间。通过在conf.c 中定义它,每个人都共享一个副本。


(a) 你的评论是:

初始化stmt中的第二个括号使它看起来像一个函数

是可以理解的,在这种情况下,它确实代表一个函数调用。但仅限于它是一个函数的指针数组,而不是一个实际的函数定义。

【讨论】:

  • 通过说“分解数据类型的声明(在不同系统之间是一致的)和数组的定义(每个系统都会改变)。”,哪一部分是数据类型?是整数还是函数?
  • @CCNA,声明就是你在标题中看到的,它将bdevsw 声明为结构类型(declare = "这存在但我还不知道它的值")。 C文件中的定义(define = "this is its value")就是你问的那个位。
  • 我误解了你所说的“数组的定义”是什么意思。您的意思是数据声明与类型定义。
  • @CCNA,我经常发现这样思考区别很有用:声明声明某事物存在而没有定义其价值是什么(尽管,根据需要,您必须说出 type 它是)。这就是标题中的内容,它指出bdevsw 存在但不创建它。另一方面,定义会创建它,这就是 C 文件中的内容。
猜你喜欢
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-24
相关资源
最近更新 更多