GNU C 、ANSI C、标准C、标准c++区别和联系

GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统。它在编写linux的时候自己制作了一个标准成为 GNU C标准。ANSI 美国国家标准协会,它对C做的标准ANSI C标准后来被国际标准协会接收成为 标准C 所以 ANSI C 和标准C是一个概念

总体来说现在linux也支持标准C,以后标准C可以跨平台,而GUN c 一般只在linux c下应用

18.1 ANSI C和标准C++的差别

这里的ANSI C指的是最新的标准-C99

1、ANSI C不支持引用

2、ANSI C不支持函数重载

3、ANSI C多了两个整型(long long、unsigned long long),不过最新的C++编译器已经支持这两种整型

4、ANSI C不支持C++中的一个变量初始化方式,例如:int a(8);

5、ANSI C声明结构时必须使用struct关键字,而标准C++不需要

6、ANSI C标准库中的一些头文件,在标准C++中有了新的名称,例如ctime、cstring、climits、cfloat、cctype,有些文件不仅是名称上的变化

7、ANSI C不支持名称空间

8、ANSI C不包含bool类型,以及true和false关键字

9、声明函数时,参数为空的含义不同。在ANSI C中表示接受任意个数的参数,而在标准C++中表示不接受参数

10、ANSI C不支持内联函数

11、ASNI C不支持默认参数

12、ANSI C不支持可用于全局变量的作用域解析操作符(::)

13、使用const定义的全局常量在ANSI C中具有外部链接性,在标准C++中具有内部链接性,所以在标准C++中声明外部链接性的全局常量必须使用extern,例如:extern const int a = 10;

18.02GNU CANSI C扩展的地方

1.允许零长度数组

GNU C允许零长度数组,在定义变长对象的头结构时,这个特性非常有用。

struct var_data

{

int len;

char data[0];

};

char data[0]仅仅意味着程序中通过var_data的结构体实例的data[index]成员可以访问len之后的第index个地址,并没有为data[0]分配内存。

假设struct var_data的数据域保存在struct var_data紧接着的内存区域,通过如下代码可以遍历这些数据:

struct var_data s;

for (i=0;i<s.len;i++)

{

printf(“%02x”,s.data[i]);

}

2、case范围

GNU C 支持case x…y 这样的语法,区间[x,y]的数都会满足这个case的条件,记得数据结构试验时,有的同学为了做菜单使用了仅100个case,还好我做的是GUI的

switch(c)

{

case ’0′…’9′: c-=’0′;

break;

case ‘a’…’f‘: c-=’a‘-10;

break;

case ‘A’…’F‘: c-=’A‘-10;

break;

}

这个case的特点大家都看得出来,比标准C少敲了多少case啊

3、语句表达式

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

#define min_t(type,x,y) /

({type __x=(x); type __y=(y);__x<__y?__x:__y})

int ia,ib,mini;

mini=min_t(int,ia,ib);

这样,因为重新定义了__x和__y这两个局部变量,所以上述方法定义的宏将不会有副作用。在标准C中,对应的宏通常会有副作用:

#define min(x,y) ((x)<(y)?(x):(y))

而代码min(++ia,++ib)将会被展开为

((++ia)<(++ib)?(++ia):(++ib)) 传入宏的参数会被增加两次。

这个在 嵌入式程序员应知道的0×10个基本问题 里有讲过。

4、typeof关键字

typeof(x)语句可以获得x的类型,因此,我们可以借助typeof重新定义第3条提到的min_t这个宏

#define min(x,y) /

({ /

const typeof(x) _x=(x);/

const typeof(y) _y=(y);/

(void) (&_x==&_y);/

_x<_y ? _x: _y ; })

我们不需要像第三条时那样传一个type进去,因为通过typeof(x)可以得到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”)

而不是 printk(“success!/n”,);

6.标号元素

标准c要求数组或结构体的初始化值必须以固定的顺序出现,在GNU C中,通过指定索引或结构体成员名,允许初始化值得以任意顺序出现。

指定数组索引的方法是在初始化值前添加 [INDEX]= ,当然也可以用 [FIRST...LAST]= 的形式指定一个范围。例如下面的代码定义一个数组,并把其中的所有元素赋值为0:

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

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

struct file_operations DEMO_fops = {

owner :    THIS_MODULE,

llseek:      DEMO_llseek,

read:       DEMO_read,

write:       DEMO_write,

ioctl:        DEMO_ioctl,

open:        DEMO_open,

release:   DEMO_release,

};

但是Linux 2.6还是推荐采用标准C的方式,如下

struct file_operations DEMO_fops = {

.owner =    THIS_MODULE,

.llseek =   DEMO_llseek,

.read =     DEMO_read,

.write =    DEMO_write,

.ioctl =    DEMO_ioctl,

.open =     DEMO_open,

.release = DEMO_release,

};

7.当前函数名

GUN C预定义了两个标识符保存当前的函数名,__FUNCTION__保存函数在源码中的名字,

__PRETTY_FUNCTION__保存带语言特色的名字。在c函数中,这两个名字是相同的。

void example()

{

printf(“This is function: %s “,__FUNCTION__);

}

代码中的__FUNCTION__意味着字符串”example”

8、特殊属性声明

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

其中ATTRIBUTE为属性说明,如果存在多个属性,则以逗号分隔。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,1,2)));

详细的可以看http://blog.163.com/sunm_lin/blog/static/9192142200741533038695/

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

aligned属性指定结构体、变量、联合体的对齐方式。packed属性作用于变量和类型,表示压缩结构体,使用最小的内存。

struct examprl_struct

{

char a;

int b;

long c;

}__attribute__((packed));

注意,这个__attribute__((packed))只能用在GNU C

关于在VC下的结构体对齐,参照http://hi.baidu.com/deep_pro/blog/item/421db081aeb604debd3e1e01.html

9、内建函数

GNU C 提供了大量的内建函数,其中很多是标准 C 库函数的内建版本,例如memcpy,它们与对应的 C 库函数功能相同,本文不讨论这类函数,其他内建函数的名字通常以 __builtin 开始。

* __builtin_return_address (LEVEL)

内建函数 __builtin_return_address 返回当前函数或其调用者的返回地址,参数LEVEL 指定在栈上搜索框架的个数,0 表示当前函数的返回地址,1 表示当前函数的调用者的返回地址,依此类推。例如:

++++ kernel/sched.c

437:                 printk(KERN_ERR “schedule_timeout: wrong timeout ”

438:                        “value %lx from %p/n”, timeout,

439:                        __builtin_return_address(0));

* __builtin_constant_p(EXP)

内建函数 __builtin_constant_p 用于判断一个值是否为编译时常数,如果参数 EXP 的值是常数,函数返回 1,否则返回0。例如:

++++ include/asm-i386/bitops.h

249: #define test_bit(nr,addr) /

250: (__builtin_constant_p(nr) ? /

251: constant_test_bit((nr),(addr)) : /

252: variable_test_bit((nr),(addr)))

很多计算或操作在参数为常数时有更优化的实现,在 GNU C 中用上面的方法可以根据参数是否为常数,只编译常数版本或非常数版本,这样既不失通用性,又能在参数是常数时编译出最优化的代码。

* __builtin_expect(EXP, C)

内建函数 __builtin_expect 用于为编译器提供分支预测信息,其返回值是整数表达式 EXP 的值,C 的值必须是编译时常数。例如:

++++ include/linux/compiler.h

13: #define likely(x)       __builtin_expect((x),1)

14: #define unlikely(x)     __builtin_expect((x),0)

++++ kernel/sched.c

564:         if (unlikely(in_interrupt())) {

565:                 printk(”Scheduling in interrupt/n”);

566:                 BUG();

567:         }

这个内建函数的语义是 EXP 的预期值是 C,编译器可以根据这个信息适当地重排语句块的顺序,使程序在预期的情况下有更高的执行效率。上面的例子表示处于中断上下文是很少发生的,第 565-566 行的目标码可能会放在较远的位置,以保证经常执行的目标码更紧凑。

时间: 2024-11-03 23:39:01

GNU C 、ANSI C、标准C、标准c++区别和联系的相关文章

C++标准库和stl区别

C++库目录:开发工具和语言-visual studio文档-visual C++-参考信息-库参考-standard C++ library C#库目录:C#使用.NET Framework 类库..NET开发-.NET Framework SDK-.NET Framwork-.NET Framework 类库 C++标准库的内容分为10类: C1.语言支持 C2.输入/输出 C3.诊断 C4.一般工具 C5.字符串 C6.容器 C7.迭代器支持 C8.算法 C9.数值操作 C10.本地化 又

oracle标准版、企业版区别

一.Oracle 9i标准版.企业版 Oracle 9i标准版 Oracle 9i企业版 ?Jserver Enterprise Edition ?InterMedia ?Enterprise Manager ?Workflow Standard Edition ?Standard Management Pack ?Object Option ?Networking kit ?Object for OLE ?Distributed Option ?64 bit Option ?ODBC Driv

Java实现3DES加密--及ANSI X9.8 Format标准 PIN PAN获取PIN BlOCK

1, 采用银联ANSI X9.8标准 PIN xor PAN获取PIN BlOCK 2, 采用3Des进行加密 参考: des和3Des加密算法实现 要点:因为3DES是对称加密算法,key是24位,当只有16位时,后8位取key的前8位 ANSI X9.8标准 PIN xor PAN获取PIN BlOCK (1) ANSI X9.8 Format(不带主账号信息) PIN(个人识别码 Personal Identity Number)总共有8个byte长度,分为两个部分;(类似数据包的格式)

文件IO函数和标准IO库的区别

摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lseek,close.称之为不带缓存的IO(unbuffered I/O).不带缓存指的是每个read,write都调用内核中的一个系统调用. 2,标准IO库,由ANSI C标准说明.标准IO库处理很多细节.例如缓存分配,以优化长度执行IO等.标准的IO提供了三种类型的缓存. (1)全缓存:当填满标准IO

linux重定向标准输入输出,标准错误

标准输入是文件描述符0.它是命令的输入,缺省是键盘,也可以是文件或其他命令的输出.标准输出是文件描述符1.它是命令的输出,缺省是屏幕,也可以是文件.标准错误是文件描述符2.这是命令错误的输出,缺省是屏幕,同样也可以是文件. 一般程序的错误和状态输出都属于标准错误. 重定向标准输出: ls >ls.out 重定向标准输入: sort < name.txt   // sort命令的输入是采用重定向的方式给出的,不过也可以直接把相应的 重定向标准错误: grep color file 2> r

标准正态分布+标准正态分布概率表+分布函数+积分

X~N(μ,σ²):一般正态分布:均值为μ.方差为σ² http://blog.csdn.net/zhanghongxian123/article/details/39008493 对于标准正态分布来说,存在一张表,称为:标准正态分布表: 该表计算的是:P(X<=x)[某个数落在某个[[email protected],x]]的概率.也就是下面阴影图形所示的面积: 如果x=1.96.则将1.96拆分为1.9和0.06.横轴1.9和纵轴0.06的交汇处:0.975.就是x<=1.96的概率. 也

网站前端_Bootstrap.基础入门.0001.BS的模版标准/样式标准/脚本标准?

简单介绍: 1. Bootstrap于2010年Twitter开源将常见的CSS布局小组件和JS插件进行了封装,大大规范且提高了代码质量及开发效率. 2. Bootstrap包含完整的基础CSS插件,丰富的预定义样式表,基于JQuery的JS插件集,非常灵活的响应式删栏系统,支持跨平台,且完全支持自定义. 注意: Bootstrap的所有JS插件都依赖jQuery库,所以要确保在使用这些功能的时候引用相应的jQuery文件 模版标准: <!DOCTYPE html> <html lang

U8客开插件-一、标准单据标准按钮执行前验证操作

今天要做的就是在标准的单据的标准按钮之前进行验证操作,如果验证通过执行保存,如果不通过给予提示不进行保存. 下面拿销售出库单的保存按钮进行举例: 第一步:在程序中 ctrl+Shift  点击保存之后用写字板,粘贴  key 取到 : 单据Key=0303.保存,按钮Tooltip:保存     F6,按钮Key:tlbSave; 第二步:VB工程及保存按钮前操作类 Public Function BeforeRunSysCommand(ByVal objLogin As Object, _ B

判断体重是否标准 男标准=身高-100&#177;3 女标准=身高-110&#177;3

while (true) { Console.WriteLine("姓名"); Console.ReadLine(); Console.WriteLine("性别"); string a = Console.ReadLine(); Console.WriteLine("身高"); double b = double.Parse(Console.ReadLine()); Console.WriteLine("体重"); doub

主要几个发行版的 gcc 对 c++ 新标准的支持情况区别

纯自用总结,无任何技术含量, 结论是,基本没区别.... 目前常用的系统: debian系的 与centOS7对应的 ubuntu14.04LTS g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4 最新的16.04LTS g++ (Ubuntu 5.3.1-10ubuntu2) 5.3.1 20160225 --------------------------------------------------- 查看redhat系列的版本: cat /etc/re