Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9463479
  • 博文数量: 1750
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20091
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1750)

文章存档

2024年(26)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: LINUX

2012-03-10 15:09:11

5 Extensions to the C Language Family

5.14 array of length zero

0长数组在GNU C中是允许的,0长数组的实现使得可变长数组的实现。

例如,

       Struct line{

              Int length;

              Char contents[0];

};

对于32位处理器,sizeofline=4;

Struct line *thislne =(struct line *)malloc(sizeof(struct line)+this_length);

Thisline->length=this_length;

只多花销一个sizeof(int)length,就可以实现变长数组

对数组的赋值通过thisline->contents[i]来实现

 

5.17 宏与可变数量的参数

print系列中最多用到可变数量的参数(可以看va_list)

而在宏中#define debug(format,args,…)  fprintf(stderr,format,args)

这里会出现一个问题,

如果调用debug(“A message”),对于后面没有参量的,则宏展开后会成为

Fprintf(stderr,”A message”,)这里会出现’,’

为解决这个问题,会使用##

所以#define debug(format,args,…) fprintf(stderr,format,##args)

 

5.21 非初始化为常量

例如

       Foo(float f,float g)

{

       Float beat_freqs[2]={f-g,f+g};

/*…*/

}

 

5.23 designated initializers

关于指定初始化在驱动中经常用到,

有很多种用法,如

To specify an array index ,write ‘[index]= ‘ befroe the element value

int a[6]={[4]=29,[2]=15};

To initialize a range of elements to the same value,write ‘[first … last]=value’.

This is a GNU extension

int widths[]={[0 … 9]=1,[10 … 99]=2,[100]=3};

In a structure initializer,specify the name of a field to initialize with ‘.fieldname=’

Before the element value.

Struct point {int x,y};

Struct point p={

.y=yvalue;

.x=xvalue;

}

You can also use a designator when initializing a union ,to specify which element of the union should be used.

Union foo{ int i;double d;};

Union foo f={.d=4};

 

5.24 case ranges

制定一个case 范围

Case low … high

注意: case 1 … 5  而不能写成 case 1…5 否则会有语法错误

 

5.26 mixed declarations and code

       Int i;

       /*…*/

       i++;

       int j=i+2;

 

5.27 declaring attributes of functions

       In GNU C,you declare certain things about functions called in your program which help the complier optimize function calls and check you code more carefully.

       Keyword __attribute__

       Alias(“target”)     对函数的另一个申明

                     Void __f () {/*do something*/}

                     Void f() __attribute__ ((weak,alias(“__f”)));

       f是对__f的弱申明

       aligned(alignment)

       alloc_size

       always_inline

       dllimport  dllexport

       deprecated

       dllexport __declspec(dllexport)      __attribute((dllexport))

       dllimport

       interrupt  void f() __attribute__ ((interrupt(“IRQ”)));

       noinline  asm(“”)

       section(“section-name”)

              extern void foobar (void) __attribute__ ((section(“bar”)));

       用于制定函数所在的段

       packed __attribute__ ((packed)) packed属性用来申明尽量最小字节的对齐

 

5.34 specifying attribute of variables

       i386 variable attribute

       handling of zero-length bitfields

       (1)

       If a zero-length bitfields is inserted between two bitfields that would normally be coalesced, the bitfields will not be coalesced.

       Example:

              Struct

              {

                     Ulong bf_1: 12;

                     Ulong :0;

                     Ulong bf_2:12;

}t1;

       0长的bitfield插入,sizeoft1=8 bytes

       如果没有0bitfield,则sizeoft1)会是4bytes

       (2)

If a zero-length bitfield is inserted after a bitfield, foo, and the alignment

of the zero-length bitfield is greater than the member that follows it, bar,

bar will be aligned as the type of the zero-length bitfield.

For example:

struct

{

char foo : 4;

short : 0;

char bar;

} t2;

struct

{

char foo : 4;

short : 0;

double bar;

} t3;

For t2, bar will be placed at offset 2, rather than offset 1. Accordingly,

the size of t2 will be 4. For t3, the zero-length bitfield will not affect the

alignment of bar or, as a result, the size of the structure.

Taking this into account, it is important to note the following:

1. If a zero-length bitfield follows a normal bitfield, the type of the zerolength

bitfield may affect the alignment of the structure as whole. For

example, t2 has a size of 4 bytes, since the zero-length bitfield follows

a normal bitfield, and is of type short.

2. Even if a zero-length bitfield is not followed by a normal bitfield, it

may still affect the alignment of the structure:

struct

{

char foo : 6;

long : 0;

} t4;

Here, t4 will take up 4 bytes.

3. Zero-length bitfields following non-bitfield members are ignored:

struct

{

char foo;

long : 0;

char bar;

} t5;

Here, t5 will take up 2 bytes.

      

      

5.55    二进制前缀0b定义二进制变量

The following statements are identical:

       i=42;

       i=0x2a;

       i=052;

       i=0b10101000;

      

5.46 第五章还提到offsetof,这里举驱动中经常用到container_of为例分析(list_entry)通过结构中的某个变量获取结构本身的指针

 Container_of ---cast a member of a structrue out to the containg structure      

@ptr : the pointer to the member

@ type: the type of the container struct this is embeded in

@member: the name of the member within the struct

 

#define container_of (ptr,type,member)({/

                        Const typeof(((type*)0)->member)*__mptr=(prt);/

                        (type *)((char *)__mptr-offsetof(type,member));})

 

#define offsetof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER)

 

首先offsetof得到memberstruct中的偏移量,(type*0->member是强制将结构指针设置为0地址的结构指针

__mptr是结构中member的指针,通过(char *)指针减去偏移量就得到所需结构的指针(当然需要指针转换)

之所以要强制转换成(char *)指针是因为不能保证member的类型,如果非(char *)指针,在偏移上会出现sizeofmember类型)*offsetof(type,member)的偏移

 

前段时间上网看到一个帖子,说是在结构中如果有0长数组的时候,offsetof的获取会出现问题,这个本身也是由于0长数组决定的,需要在使用的时候注意。

例如,

#include"stdio.h"

 

#define offsetof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER)

#define container_of(ptr,type,member) ({/

                         typeof(((type *)0)->member)* __mptr=(ptr);/

                        (type *)( (char *)__mptr-offsetof(type,member));})

struct test

{

                  char h[10]; //这里设置10而不设置12是为了0长数组和4字节对齐

                  char hhh[0];??

                  int m;

}hello={"222",1,0x11};

int main(int argc,char **argv)

{

                        struct test *hello_temp=container_of(&hello.m,struct test,m);

                        for(int i=0;i<16;i++)

                        printf("%x ",*((char *)hello_temp+i));

                        return 0;

}

hhh[0]是占指针,但是无数据的,定义hello{222”,1,0x11},结果正确,

如果hello={“222”,0x11} 此时0x11是赋给hhh[0],虽然在结构上此值不赋给对应的地址,但是也不会赋值给变量m,所以定义此类结构,需要填充对应的空数据。

事实上我觉得这样定义结构是不合理的,gcc定义0长数组是为了实现变长数组,故最好将0长数组放置于结构尾。
阅读(2326) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~