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设备驱动开发详解》宋宝华

时间: 2024-10-01 13:26:50

GNU C 与 ANSI C的区别的相关文章

C语言中void*详解及应用

 void在英文中作为名词的解释为"空虚:空间:空隙":而在C语言中,void被翻译为"无类型",相应的void *为"无类型指针".void似乎只有"注释"和限制程序的作用,当然,这里的"注释"不是为我们人提供注释,而是为编译器提供一种所谓的注释. 本文地址:http://www.cnblogs.com/archimedes/p/c-void-point.html,转载请注明源地址. void的作用: 1

void及void指针含义的深刻解析

转载地址:http://blog.csdn.net/geekcome/article/details/6249151 void的含义:     void即"无类型",void *则为"无类型指针",可以指向任何数据类型. void指针使用规范:     ①void指针可以指向任意类型的数据,亦即可用任意数据类型的指针对void指针赋值.例如:     int * pint;     void *pvoid;     pvoid = pint; /* 不过不能 pin

C/C++学习 ---- void及void指针含义的深刻解析

 原文转载自:http://blog.csdn.net/geekcome/article/details/6249151 1. void的含义 void即"无类型",void *则为"无类型指针",可以指向任何数据类型. 2. void指针使用规范①void指针可以指向任意类型的数据,亦即可用任意数据类型的指针对void指针赋值.例如: int * pint; void *pvoid; pvoid = pint; /* 不过不能 pint= pvoid; */如果要

C/C++语言void及void指针《转》

1.概述许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧.2.void的含义 void的字面意思是"无类型",void *则为"无类型指针",void *可以指向任何类型的数据.void几乎只有"注释"和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错

linux C杂记(一)

1.linux常识汇总: GNU=GNU's Not UNIX,为了区别于UNIX系统: Linux是类UNIX操作系统,免费.开源是其最大的特点,是多用户多任务且符合POSIX标准的操作系统: 目标:非私有的.开放的操作系统: 条款:GPL=General Public Licence: UNIX与Linux区别:UNIX大多与硬件配套,而linux可运行在多种硬件平台上: 1991年由Linus Torvalds开发,1994年发布Linux1.0: Linux2.6.10:2是主版本号,6

mfc-外部依赖项中再添加.h文件

问题描述 外部依赖项中再添加.h文件 用vs2010建立的MFC程序,怎么在外部依赖项中再添加.h文件 解决方案 1.将过去的工程用VS2010打开的时候.你有可能会遇到一大堆的警告:warning C4996. 比如:warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation use _CRT_SECURE_

《Linux设备驱动开发详解 A》一一3.5 Linux下的C编程特点

3.5 Linux下的C编程特点 3.5.1 Linux编码风格 Linux有独特的编码风格,在内核源代码下存在一个文件Documentation/CodingStyle,进行了比较详细的描述. Linux程序的命名习惯和Windows程序的命名习惯及著名的匈牙利命名法有很大的 不同. 在Windows程序中,习惯以如下方式命名宏.变量和函数: #def?ine PI 3.1415926 / 用大写字母代表宏 / int minValue, maxValue; / 变量:第一个单词全小写,其后单

ANSI,Unicode,UTF-8网页编码的区别

1.ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte).也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000到11111111. 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定.这被称为ASCII码,一直沿用至今. ASCII码一共规定了128个字符的编码,

ANSI、UNICODE、UTF-8、GB2312、GBK、DBCS、UCS的区别和由来。

科普一下,自己也学习一下~~~~~       一直对字符的各种编码方式懵懵懂懂,什么ANSI.UNICODE.UTF-8.GB2312.GBK.DBCS.UCS--是不是看的很晕,假如您细细的阅读本文你一定可以清晰的理解他们.Let's go!              很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状态是好的,于是他们把这称为"字节".     再后来,他们又做了一些可以处理这些字节的机器,机器开动了,