Linux 系统上可用的C编译器是GNU C编译器,它建立在自由软件基金会的编程许可证的基础上,因此可以自由发布。GNU C对标准C 进行一系列扩展,以增强标准C的功能。

1、零长度数组
GNU C 允许使用零长度数组,多用在定义变长对象的头结构。
例如:

struct var_data
{
int len;
char data[];
};

char data[0] 仅仅意味着程序中通过 var_data 结构体实例的 data[index] 成员可以访问 len 之后的第 index 个地址,它并没有为 data[] 数组分配内存,因此 sizeof(struct var_data)=sizeof(int)。
假设 struct var_data 的数据域保存在 struct var_data 紧接着的内存区域,通过如下代码可以遍历这些数据:

struct var_data s;
...
for (i=;i<s.len;i++)
{
printf("%02x", s.data[i]);
}

2、case范围
GNU C 支持 case x...y 这样的语法,区间[x,y]的数都会满足这个 case 的条件。
例如:

switch (ch)
{
case ''...'': c -= '';
break;
case 'a'...'f': c -= 'a' - ;
break;
case 'A'...'F': c -= 'A' - ;
break;
}

3、语句表达式
GNU C 把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方。我们可以在语句表达式中使用原本只能在复合语句中使用的循环变量、局部变量等。
例如:

#define min_t(type, x, y) \
({type __x = (x); type __x = (x); __x < __y ? __x : __y;}) int ia, ib, mini;
float fa, fb, minf; mini = min_t(int, ia, ib);
minf = min_t(float, fa, fb);

因为重新定义了 __x 和 __y 这两个局部变量,所以以上述的方式定义的宏将不会有副作用。
在标准C中,对应的如下宏则会产生副作用:
#define min(x, y) ((x) < (y) ? (x) : (y))
代码 min(++ia, ++ib) 会被展开为 ((++ia) < (++ib) ? (++ia) : (++ib)),传入宏的参数被增加两次。

4、typeof 关键字
typeof(x) 语句可以获得 x 的类型,因此,我们可以借助 typeof 重新定义 min 这个宏:

#define min(x, y) ({ \
const typeof(x) _x = (x); \
const typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })

我们不需要像 min_t(type, x, y) 这个宏那样把 type 传入,因为通过 typeof(x)、typeof(y)可以获得 type。代码行 (void) (&_x == &_y) 的作用是检查 _x 和 _y 的类型是否一致。

5、可变参数的宏
标准C只支持可变参数的函数,意味着函数的参数是不固定的,例如 printf() 函数原型为:

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

而在 GNU C 中,宏也可以接受可变数目的参数,例如:

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

这里arg表示其余的参数可以是零个或者多个,这些参数以及参数之间的逗号构成 arg 的值,在宏扩展时替换 arg。

例如:

pr_debug("%s:%d", filename, line)

会被扩展为:

printk("%s:%d", filename, line)

使用“##”的原因是处理 arg 不代表任何参数的情况,这时候,前面的逗号就变得多余了。使用“##”之后,GNU C 预处理器会丢弃前面的逗号。

pr_debug("success!\n")

会被正确的展开为:

printk("success!\n")

6、标号元素
标准 C 要求数组或结构体的初始化值必须以固定的顺序出现,在 GNU C 中,通过指定索引或结构体成员名,允许初始化值以任意顺序出现。
指定数组索引的方法是在初始化值前添加 “[INDEX] = ”,当然也可以用 “[FIRST...LAST] = "的形式指定一个范围。例如下面的代码定义一个数组,并把其中的所有元素赋值为0:

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

下面的代码借助结构体成员名初始化结构体:

struct file_operations ext2_file_operations =
{
read: generic_file_read,
write: generic_file_write,
ioctl: ext2_ioctl,
open: generic_file_open,
release: ext2_release_file,
};

但是,Linux2.6推荐类似的代码应该尽量采用标准C的方式,如下:

struct file_operations ext2_file_operations =
{
.read = generic_file_read,
.write = generic_file_write,
.ioctl = ext2_ioctl,
.open = generic_file_open,
.release = ext2_release_file,
};

7、当前函数名
GNU C 预定义了两个标识符保存当前函数的名字,__FUNCTION__保存函数在源码中的名字,__PRETTY_FUNCTION__保存带语言特色的名字。在C函数中,这两个名字是相同的。

void test(void)
{
printf("This is function:%s\n", __FUNCTION__);
}

8、特殊属性声明
GNU C 允许声明函数、变量和类型的特殊属性,以便进行手工的代码优化和定制代码检查的方法。指定一个声明的属性,只需要在声明后面添加 __attribute__ ((ATTRIBUE))。其中 ATTRIBUE 为属性说明,如果存在多个属性,则以逗号分隔。
GNU C 支持 noreturn、format、section、aligned、packed 等十多个属性。
noreturn 属性作用于函数,表示该函数从不返回。这会让编译器优化代码,并消除不必要的警告信息。
例如:

#define ATTRIB_NORET __attribute__((noreturn)) ....
asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;

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

asmlinkage int printk(const char *fmt, ...) __attribute__ ((format(printf, , )));

上述代码中的第一个参数时格式串,从第二个参数开始都会根据 printf() 函数的格式串规则检查参数。
unused 属性作用于函数和变量,表示该函数或变量可能不会被用到,这个属性可以避免编译器产生警告信息。
aligned 属性用于变量、结构体或联合体,指定变量、结构体或联合体的对齐方式,以字节为单位。
例如:

struct example_struct
{
char a;
int b;
long c;
} __attribute__((aligned()));

表示该结构体类型的变量以4字节对齐。

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

struct example_struct
{
char a;
int b;
long c __attribute__((packed));
};

9、内建函数
GNU C 提供大量的内建函数,其中大部分是标准C库函数的 GNU C 编译器内建版本,例如 memcpy() 等,它们与对应的标准C库函数功能相同。
不属于内建函数的其他内建函数的命名通常以 __builtin 开始。
内建函数__builtin_return_address (LEVEL)返回当前函数或其调用者的返回地址,参数LEVEL 指定调用栈的级数,如0 表示当前函数的返回地址,1表示当前函数的调用者的返回地址。
内建函数__builtin_constant_p(EXP)用于判断一个值是否为编译时常数,如果参数EXP 的值是常数,函数返回 1,否则返回 0。
内建函数__builtin_expect(EXP, C)用于为编译器提供分支预测信息,其返回值是整数表达式 EXP 的值,C 的值必须是编译时常数。
例如:下面的代码检测第 1 个参数是否为编译时常数以确定采用参数版本还是非参数版本的代码:

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

Linux GNU C的更多相关文章

  1. alias function varibales in Linux/GNU and Mac alias命令细说

    细说,在古文言中是”奸细佞臣的话“,现如今成了”详细说明“的缩略. alias是MS-DOC中cmds中doskey的counterpart,是”别名“或者”化名“的意思 alias强大之处在于可以化 ...

  2. How-to Install VMware Tools on Debian Stretch 9 32/64bit Linux+GNU

    在虚拟机VMWARE上安装debian9 安装vmwaretools时候遇到问题 询问我IFCONFIG安装在哪里? 新版的debian不知道是用户权限问题还是使用了其他网络配置工具 vmwareto ...

  3. Beginning Linux Programming 学习--chapter 1 Getting start--What's linux,GNU,HeaderFiles, Libraries

    "文明的建立的不是机器而是思想" -- 托尔斯泰 Linux truly become a viable operating system, especially in the s ...

  4. Linux GNU GAS introduction

    Linux汇编语法简介(GNU GAS)     声明:本教程不是介绍汇编语言和CPU指令的书籍,只是对gas的用法做一简单介绍.市面上所有讲汇编的书都是在微软的环境下,使用的是Intel的语法格式, ...

  5. Terminal的快捷键 for Terminal for Mac OS 10.10, Linux/GNU(Ubuntu, deepin, elementory os,CentOS)

    对于习惯用windows键盘的,突然转成Mac蓝牙键盘真的有点不习惯,尤其是多了⌘这个键,还有Alt键也成了Option 但是对于Windows下熟悉的快捷键,它们真的失效了,还好Ubuntu也常用, ...

  6. history and its relevant variables in Linux/GNU and Mac OS history命令以及相关环境变量

    对于Terminalor们,history命令并不陌生,什么!n, !!更是很常用的,而且您在命令行敲的cmds是默认保存在/home/$USER/.bash_history(linux) /User ...

  7. 你可能不知道的Linux/GNU bash sort多列排序功能

    (转载请注明原创于潘多拉盒子) Linux man pages的缺点就是,如果你不会用某个命令,那么看完了多半还是不会.原因是,没有例子!比较囧吧? sort是提供了多列排序的功能的.通过-k选项,可 ...

  8. 世纪大争论:Linux还是GNU/Linux?

    我们在网上已经习惯用“Linux”来称呼Linux操作系统了,然而,偶尔也用“GNU/Linux”来称呼和指代同样的操作系统和软件.同时人们也在争论这两种称呼哪个更合适. 本文将不会选边站队,仅力图向 ...

  9. GNU/Linux 介绍

    在了解Linux之前要先了解什么是GNU / GNU官方解释? GNU是一个自由软件操作系统.就是说,它尊重其使用者的自由.GNU操作系统包括GNU软件包(专门由GNU工程发布的程序)和由第三方发布的 ...

随机推荐

  1. windows下配置cuda9.0和pytorch

    今天看了看pytorch官网竟然支持windows了,赶紧搞一个. 下载cuda 9.0  https://developer.nvidia.com/cuda-downloads 下载anaconda ...

  2. zoj 2966 Build The Electric System(最小生成树)

    Build The Electric System Time Limit: 2 Seconds      Memory Limit: 65536 KB In last winter, there wa ...

  3. 利用有道翻译Api实现英文翻译功能

    有道翻译提供了翻译和查词的数据接口.通过数据接口,您可以获得一段文本的翻译结果或者查词结果.       通过调用有道翻译API数据接口,您可以在您的网站或应用中更灵活地定制翻译和查词功能. 第一步: ...

  4. 在pycharm中自定义模板代码,快速输出固定代码块

    pycharm中有时会经常输出固定一段代码,为避免每次重复输入,可以自定义一段模板代码,请看以下图教程: 1.  点击 file   里面的   setting 2. 在搜索框输入live,就会显示出 ...

  5. New Concept English there (6)

    30w/m The expensive shops in a famous arcade near Piccadilly were just opening. At this time of the  ...

  6. keepererrorcode = connectionloss for 错误处理

    自己的环境在虚拟机上,于是使用同事的环境调试问题,发现无法初始化成功,提示keepererrorcode = connectionloss for,于是上网查了下资料整理如下: 1.对比代码中引用的j ...

  7. HTML, CSS. JS的各种奇葩bug

    1. block包含inline-block的时候, inline-block 没有内容的时候,会根据 font 产生一个 line-height 来产生一个空白块. 解决方法: <div cl ...

  8. 《Tomcat内核设计剖析》京东评论过百

    到京东看了下<Tomcat内核设计剖析>评论都一百多了,上个月也第二次印刷了,这里看下好评.中评和差评. 好评: 中评 对于中评,请看 为什么<写Tomcat内核设计剖析>,就 ...

  9. IOS开发 多线程编程 - NSOperationQueue

    一.简介 一个NSOperation对象可以通过调用start方法来执行任务,默认是同步执行的.也可以将NSOperation添加到一个NSOperationQueue(操作队列)中去执行,而且是异步 ...

  10. keras channels_last、preprocess_input、全连接层Dense、SGD优化器、模型及编译

    channels_last 和 channels_first keras中 channels_last 和 channels_first 用来设定数据的维度顺序(image_data_format). ...