嵌入式C语言自我修养02:Linux内核驱动中的指定初始

  

2.1什么是指定初始化

  

在标准C中,当我们定义并初始化一个数组时,常用方法如下:

  
 <代码> int[10]={0, 1, 2, 3, 4, 5, 6, 7, 8};  
  

按照这种固定的顺序,我们可以依次给一个[0]和[8]赋值。因为没有对一个[9]赋值,所以编译器会将一个[9]默认设置为0。当数组长度比较小时,使用这种方式初始化比较方便。当数组比较大,而且数组里的非零元素并不连续时,这时候再按照固定顺序初始化就比较麻烦了。

  

比如,我们定义一个数组b[100],其中b [10], b[30]需要初始化,如果还按照前面的固定顺序初始化,{}中的初始化数据中间可能要填充大量的0,比较麻烦。

  

那怎么办呢? C99标准改进了数组的初始化方式,支持指定任意元素初始化,不再按照固定的顺序初始化。

  b
 <代码> int[100]={[10]=1,[30]=2};  
  

通过数组索引,我们可以直接给指定的数组元素赋值。除此之外,一个结构体变量的初始化,也可以通过指定某个结构体域直接赋值。

  

因为GNU C支持C99标准,所以GCC编译器也支持这一特性。甚至早期不支持C99,只支持C89的GCC编译器版本,这一特性也被当作一个GCC编译器的扩展特性来提供给程序员使用。

  

2.2指定初始化数组元素

  

在GNU C中,通过数组元素索引,我们就可以给某个指定的元素直接赋值。

  b
 <代码> int[100]={[10]=1,[30]=2};  
  

在{}中,我们通过[10]数组元素索引,就可以直接给一个[10]赋值了。这里有个细节注意一下,就是各个赋值之间用逗号”、“隔开,而不是使用分号“;”。

  

如果我们想给数组中某一个索引范围的数组元素初始化,可以采用下面的方式。

  
 <代码> int主要(空白)
  {
  int b [100]={[10…30]=1,[50…60]=2};
  for (int i=0;我& lt;100;我+ +)
  {
  printf (" % d”,[我]);
  如果(我% 10==0)
  printf (" \ n ");
  }
  返回0;
  } 
  

在这个程序中,我们使用[10…30)表示一个索引范围,相当于给一个[10]到[30]之间的20个数组元素赋值为1。

  

GNU C支持使用…表示范围扩展,这个特性不仅可以使用在数组初始化中,也可以使用在切换实例语句中。比如下面的程序:

  
 <代码> # include
  int主要(空白)
  {
  int i=4;
  开关(我)
  {
  案例1:
  printf (" 1 \ n”);
  打破;
  案例2…8:
  printf (" % d \ n”,我);
  打破;
  例9:
  printf (" 9 \ n ");
  打破;
  默认值:
  printf(“违约! \ n”);
  打破;
  }
  返回0;
  } 
  

在这个程序中,当情况值为2到8时,都执行相同的情况下分支,可以通过案例2…8:的形式来简化代码。这里同样也有一个细节需要注意,就是……和其两端的数据范围2和8之间也要空格,不能写成2…8的形式,否则编译就会通不过。

  

2.3指定初始化结构体成员变量

  

跟数组类似,在标准C中,结构体变量的初始化也要按照固定的顺序。在GNU C中我们也可以通过结构域来初始化指定某个成员。

  
 <代码> struct学生{
  char[20]名称;
  int年龄;
  };
  
  int主要(空白)
  {
  struct学生stu1={20}“智慧”;
  printf (" % s: % d \ n”, stu1.name, stu1.age);
  
  struct学生stu2={
  . name=" wanglitao ",
  .age=28
  };
  printf (" % s: % d \ n”, stu2.name, stu2.age);
  
  返回0;
  } 
  

在程序中,我们定义一个结构体类型的学生,然后分别定义两个结构体变量stu1和stu2。初始化stu1时,我们采用标准C的初始化方式,即按照固定顺序直接初始化。初始化stu2时,我们采用GNU C的初始化方式,通过结构域名. name和.age,我们就可以给结构体变量的某一个指定成员直接赋值。非常方便。

  

2.4 Linux内核驱动注册

  

在Linux内核驱动中,大量使用GNU C的这种指定初始化方式,通过结构体成员来初始化结构体变量比。如在字符驱动程序中,我们经常见到这样的初始化:

  
 <代码>静态常量struct file_operations ab3100_otp_operations={
  .open=ab3100_otp_open,
  .read=seq_read,
  .llseek=seq_lseek,
  .release=single_release,
  }; 
  

在驱动程序中,我们经常使用file_operations这个结构体变量来注册我们开发的驱动,然后以回调的方式来执行我们驱动实现的相关功能。结构体file_operations在Linux内核中的定义如下:

嵌入式C语言自我修养02:Linux内核驱动中的指定初始