GNU C 与 ANSI C的区别

Wesley13
• 阅读 498

1.零长度数组

GNU C允许使用零长度数组,定义变长度对象时比较方便

struct var_data {

    int len;

    char data[0];

};

var_data的大小仅为一个int型,data是常量地址,data[index]是访问其后的内存空间。

struct var_data *s = malloc(sizeof(var_data) + len);

释放内存的时候free(s)只释放int,所以还要认为地释放data空间,这会带来不便。另外只有GNU C支持,c/c++编译永远通不过。

2.case范围

GNU C支持case x...y这样的语法,区间[x ,y]都满足这个条件。例如

case 0...5 ==> case 0 : case 1: case 2: case 3: case 4: case 5: 

3.语句表达式

GNU C可以把括号中的复合语句看成是语句表达式, a=( ; ; ),于是就有了以下应用

#define min_t(type, x, y) ((type __x  = (x); typ __y = (y); __x < __y ? __x : __y;)) 

float minf  = min_t(float, f1, f2);

int mini  = min_t(int, i1, i2);

4.typeof关键字

typeof(x)语句可以获得x的类型

5.可变参数的宏

标准C只支持可变参数的函数

int printf(const char *format [, argument]...);

而GNU C也支持可变参数的宏

#define pr_debug(fmt, arg...)   printfk(fmt, ##arg)

6.标号元素

标准C要求数组或结构体的初始值必须以固定顺序出现,而GNU C可以通过指定索引和结构体成员允许初始化值以任意顺序出现([index] = ),当然也可以如下运用

unsigned char data[MAX] = {[0...MAX - 1] = 0};

下面是借助结构体成员名初始化值

struct file_operations ext2_file_operation = {

llseek: generic_file_llseek,

read: generic_file_read,

write:generic_file_write,

ioctl:ext2_ioctl,

mmap:generic_file_mmap,

open:generic_file_open,

release:ext2_release_file,

fsync:ext2_sync_file,

};

但是linux2.6推荐类似的代码应该尽量采用标准C的语法

struct file_operations ext2_file_operation = {

.llseek  =  generic_file_llseek,

.read    =   generic_file_read,

.write    =   generic_file_write,

.ioctl     =    ext2_ioctl,

.mmap =   generic_file_mmap,

.open   =generic_file_open,

.release  = ext2_release_file,

.fsync      =  ext2_sync_file,

};

7.当前函数名

GNU C预定义了两个标识符保存当前函数的名字,__FUNCTION__保存函数在源码中的名字,__PRETTY_FUNCTION__保存带语言特色的名字,而标注C两者是一样的。

void exampe()

{

    printf("This is function %s\n", __FUNCTION__);

}

8.特殊属性声明

GNU C允许声明函数,变量和类型的特殊属性,以便进行手工优化和定制代码检查的方法。指定一个属性只需在其声明后添加__attribute__((ATTRIBUTE)).

noreturn 属性作用于函数,表示该函数从不反悔。这回让编译器优化代码,并消除不必要的警告信息。

例如:void do_exit(int n) __attribute__((noreturn));

format属性也用于函数,该函数使用printf、scanf或strftime风格的参数,指定format属性可以让编译器根据格式串检查参数类型。

unused属性作用于函数和变量,表示该函数或变量可能不会被用到,这个属性可以避免编译器产生警告信息。

aligned属性用于变量、结构体或联合体,指定变量、结构体或联合体的对齐方式,以字节为单位。

例如:struct example_struct{

char a;

int b;

long c;

} __attribute__((aligned(4)));表示该结构类型的变量以4字节对齐。

packed属性作用于变量和类型,用于变量和结构体成员时表示使用最小可能的对齐,用于枚举、结构体或联合体类型时表示该类型使用最小的内存。

例如:struct example_struct{

char a;

int b;

long c __attribute__((packed));

} ;

9.内建函数

GNU C除了标准C提供的内建函数(memcpy)外,还提供了许多其他的内建函数,通常命名以__builtin开始。

__builtin_return_address(LEVEL)返回当前函数或调用这的返回地址,参数LEVEL指定调用栈的级数,如0表示当前函数的返回地址,1表示当前函数的调用者的返回地址。

__builtin_constant_p(EXP)用于判断一个值是否为编译时常数,是返回1,否则返回0.例如下面的代码检测第一个参数是否为常数以确定采用参数版本还是非参数版本

#define test_bit(nr, addr) (__builtin_constant_p(nr) ? constant_test_bit((nr), (addr)) : variable_test_bit((nr), (addr))

——记《linux设备驱动开发详解》宋宝华

本文同步分享在 博客“Engineer-Bruce_Yang”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
LeetCode 5561. 获取生成数组中的最大值
文章目录1\.题目2\.解题1\.题目给你一个整数n。按下述规则生成一个长度为n1的数组nums:nums00nums11当2<2i<n时,nums2inumsi
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
2年前
JavaScript常用函数
1\.字符串长度截取functioncutstr(str,len){vartemp,icount0,patrn/^\x00\xff/,strre"";for(vari
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这