GNU C 与 ANSI C的区别
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设备驱动开发详解》宋宝华
GNU C 与 ANSI C的区别的更多相关文章
- linux内核中GNU C和标准C的区别
linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...
- GNU C 、ANSI C、标准C、标准c++区别和联系
转载自点击打开链接 GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的.它的目标是创建一套完全自由的操作系统.它在编写linux的时候自己制作了一个标准成为 ...
- GNU C 与 ANSI C(下)
1. 语句表达式 GNU C 把包含在括号中的复合语句看做是一个表达式,称作语句表达式,它可以出现在任何允许表达式的地方.我们可以在语句表达式中使用原本只能在复合语句中使用的循环.局部变量等,例如: ...
- GNU C 与 ANSI C(上)
Linux 上可用的 C 编译器是 GNU C 编译器,它建立在自由软件基金会的编程许可证的基础上,因此可以自由发布.GNU C 是对标准 C 进行的一系列扩展,以增强标准 C 的功能. 1. 零长度 ...
- GNU C与ANSI C的不同
引用:http://tsroad.lofter.com/post/376316_57ac519 1.GNU C可定义0长度数组,目的是为了定义可变长结构体. struct var_struct{ ...
- 字符编码ANSI和ASCII区别、Unicode和UTF-8区别
ANSI码ANSI编码是一种对ASCII码的拓展:ANSI编码用0x00~0x7f (即十进制下的0到127)范围的1 个字节来表示 1 个英文字符,超出一个字节的 0x80~0xFFFF 范围来表示 ...
- C11 (GNU Dialect) -std=gnu11 和 -std=c11
C11 (GNU Dialect) -std=gnu11 和 -std=c11 C11 (GNU Dialect) -std=gnu11 和 -std=c11 用于 IntelliSense 的 C ...
- ANSI码和UNICODE码
什么是ANSI,什么又是UNICODE呢? 其实这是两种不同的编码方式标准,ANSI中的字符采用8bit,而UNICODE中的字符采用16bit. (对于字符来说ANSI以单字节存放英文字符,以双字节 ...
- GCC、g++编译器和gcc编译器的区别
GCC:(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分. gcc:GNU的C语 ...
随机推荐
- 假设一个大小为100亿个数据的数组,该数组是从小到大排好序的,现在该数组分成若干段,每个段的数据长度小于20「也就是说:题目并没有说每段数据的size 相同,只是说每个段的 size < 20 而已」
假设一个大小为100亿个数据的数组,该数组是从小到大排好序的,现在该数组分成若干段,每个段的数据长度小于20「也就是说:题目并没有说每段数据的size 相同,只是说每个段的 size < 20 ...
- 【移动开发】EditText输入字数限制总结(包括中文输入内存溢出的解决方法)
限定EditText输入个数的解决方案很多,但是一般主要考虑两点,也就是处理两件事:(1)不同语言字符(英文.中文等)处理方式(2)输入字符达到数目后,是否仍然允许用户输入 第一点,涉及的东东其实蛮多 ...
- Java实现内部类
内部类是java中非常方便的一种机制,内部类所在的类称为宿主类,即内部类只能被它的宿主类使用,用这个特性,可以很好的控制类的可见性. 接下来看一个例子: package for_apro; impor ...
- UE4读取scv文件 -- 数据驱动游戏性元素
官方文档链接:http://docs.unrealengine.com/latest/CHN/Gameplay/DataDriven/index.html 略懒,稍微麻烦重复的工作,总希望能找人帮忙一 ...
- 18 Ui美化 剪切动画clip
输入0 - 10000 让图片根据数值显示部分图片 在工程文件的res/drawable/新建clip文件 <?xml version="1.0" encoding=&quo ...
- 线程在Linux中的实现
早在以前,我们就知道,CPU调度的基本单位是线程,而进程是拥有资源的基本单位,进程是用进程描述符表示的,那么线程是怎么实现和表示的呢? 线程机制是现代编程技术中常用的一种抽象概 ...
- 03 Button 按钮
按钮 父类: TextView >概念:可以被按,点击 并且执行一个动作 >属性: 在按钮内部的上下左右设置图片: androi ...
- c++友元函数与友元类
友元函数和友元类的需要: 类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的.非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这 ...
- 【shell脚本练习】批量添加用户和设置密码
题目 添加9个用户,user101-user109:密码同用户名: 思路 for循环来添加就好了,用户名和密码都可以拼字符串来完成 user10+数字 要判断是否能添加成功,注意非交互模式下修改用户密 ...
- java组播MulticastSocket
在单播模式中有服务器端和客户端之分,而组播模式与单播模式不同,每个端都是以路由器或交换机做为中转广播站,任意一端向路由器或交换机发送消息,路由或交换机负责发送其他节点,每个节点都是同等的.所以在编程模 ...