GNU C 、ANSI C(标准C)与标准c++的区别

以下内容源于网络资源的学习与整理,如有侵权请告知删除。

概念

GNU计划在编写linux的时候自己制作了一个标准,称为GNU C标准

ANSI(美国国家标准协会)对C做了一个标准“ANSI C后来被国际标准协会接收成为标准C

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

一、ANSI C和标准C++的差别

(1)这里的ANSI C指的是最新的标准,C99。

(2)区别:

  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。

二、GNU C 比 ANSI 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的。这个case的特点大家都看得出来,比标准C少敲了多少case啊。

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

(3)语句表达式

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

#define min_t(type,x,y) ({type __x=(x); type __y=(y);__x<__y?__x:__y})int ia,ib,imin;
imin=min_t(int,ia,ib);

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

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

(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函数中,这两个名字是相同的。比如下面代码中的__FUNCTION__意味着字符串"example"。

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

(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)));

unused属性作用于函数和变量,表示该函数或变量可能不会被用到,避免编译器产生的警告信息。
aligned属性指定结构体、变量、联合体的对齐方式。
packed属性作用于变量和类型,表示压缩结构体,使用最小的内存。__attribute__((packed))只能用在GNU C。

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

(9)内建函数

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

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

printk(KERN_ERR “schedule_timeout: wrong timeout ”“value %lx from %p/n”, timeout,__builtin_return_address(0));
__builtin_constant_p(EXP)

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

//include/asm-i386/bitops.h#define test_bit(nr,addr) (__builtin_constant_p(nr) ? constant_test_bit((nr),(addr)) : variable_test_bit((nr),(addr)))

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

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

//include/linux/compiler.h
#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)//kernel/sched.c
if (unlikely(in_interrupt())) {printk(”Scheduling in interrupt/n”);BUG();
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASIHTTPRequest 常用方法讲解

原文地址&#xff1a;http://www.cocoachina.com/iphonedev/sdk/2011/0324/2736.html ASIHTTPRequest 是一款极其强劲的 HTTP 访问开源项目。让简单的 API 完成复杂的功能&#xff0c;如&#xff1a;异步请求&#xff0c;队列请求&#xff0c;GZIP 压缩&#xff0c;缓存&#x…

作业记录

老师留得题目http://oldboy.blog.51cto.com/2561410/1337343首先我用了一个我最快想到办法用了一个超级笨的办法 #!/bin/bash #(基础) pwdpwd #(临时目录) dir"htmldir" #(源文件地址) html"http://vote.runsky.com/2013/12/jiaoyu/" #(临时文件1) file1&q…

C++远航之封装篇——对象指针、this指针

1、使用new会调用构造函数&#xff0c;使用malloc不会使用构造函数。 2、加不加括号都行&#xff1f;YES 3、对象成员指针&#xff08;指针指向对象&#xff0c;而这对象是数据成员&#xff09; 4、this指针 下面这个没有歧义&#xff1a; 而下面这个有歧义&#xff1a; 为此&a…

javascript Function()

JavaScript中的Function对象是函数&#xff0c;函数的用途分为3类&#xff1a;作为普通逻辑代码容器&#xff1b;作为对象方法&#xff1b;作为构造函数。1.作为普通逻辑代码容器function multiply(x, y) { return x * y;}函数multiply封装了两位数的乘法运算公式&#xff1a;…

java基础之线程(1)

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。 每个线程都有一个优先级&#xff0c;高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时&#xff0c;该新线程的初…

poj 1274 The Perfect Stall

2019独角兽企业重金招聘Python工程师标准>>> The Perfect Stall Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16888 Accepted: 7721 Description Farmer John completed his new barn just last week, complete with all the latest milkin…

C++远征之封装篇——常对象成员、常成员函数

一、常对象成员 二、常成员函数 &#xff08;1&#xff09;常成员函数中不能修改数据成员的值 &#xff08;2&#xff09;不能修改的原因 每个函数都默认带了一个this指针的&#xff0c;该指针指向该类的实例。当使用const来修饰时&#xff0c;其实是const Coordinate* this。这…

PHP建站环境搭建:汇总网上常见的1键安装包

PHP的程序很火&#xff0c;像博客&#xff1a;Wordpress、论坛&#xff1a;Discuz!、SNS&#xff1a;UCenter Home、CMS&#xff1a;DedeCMS等等都是比较流行的PHP程序&#xff0c;大家都在使用PHP类的程序&#xff0c;但对于很多初学者来说&#xff0c;直接上传到虚拟空间上一…

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和...

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和文章作者&#xff1a;Yx.Ac 文章来源&#xff1a;勇幸|Thinking (http://www.ahathinking.com) 转载请注明&#xff0c;谢谢合作。 以后新博客写的文章挑一些粘过来&#…

JEECMS编辑漏洞及随便拿webshell,啊哈哈

JEECMS是基于java技术开发&#xff0c;继承其强大、稳定、安全、高效、跨平台等多方面的优点 采用SpringMVC3Spring3Hibernate3Freemarker主流技术架构 安全性做得非常变态&#xff0c;当网站安装完成后就不再允许执行任何目录下的jsp文件了&#xff08;web.xml配置了过滤器禁…

内核通识——linux内核的简介

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 内核下载 下载地址&#xff1a;www.kernel.org 下载地址&#xff1a;Index of /sites/ftp.kernel.org/pub/linux/kernel/ 本栏目文章2.6.35.7版本为例进行说明。 一、内核功能 1、操作系统的含义 操…

端口列表详解

tyle"margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial; color:rgb(51,51,51); text-align:left"> TCP 2Death TCP 11Skun TCP 12Bomber TCP 16Skun TCP 17Skun TCP 18消息传输协议,skun TCP 19Skun TCP 20FTP Data,Amanda TCP 21文件传…

C++之内存管理

1.申请内存&#xff1a;int *p new int;释放内存&#xff1a;delete p; 2.申请块内存&#xff1a;int *arrnew int[10];释放:delete []arr; 3.申请内存需要判断是否成功&#xff0c;释放内存需要设空指针 4.new与delete配套使用 转载于:https://www.cnblogs.com/xjyxp/p/11236…

Android 调用分享框

平时打开某些应用的分享选项时&#xff0c;经常可以看到同时分享到google play, 豌豆荚&#xff0c;91助手等弹出框&#xff0c;具体怎样实现的呢&#xff1f; 可以参考下面的代码 Uri uri Uri.parse("market://details?id"Constant.PACKAGE_NAME);Intent intent …

内核通识——linux内核源码(2.6.35.7版本)的目录结构

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、文件 &#xff08;1&#xff09;Kbuild文件 Kbuild是kernel build的缩写&#xff0c;就是内核编译的意思。这个文件就是linux内核特有的内核编译体系需要用到的文件。 &#xff08;2&#xff09…

【原创】自制PCB经验教训之一:版图打印篇

看了篇帖子《用感光电路板自制PCB攻略&#xff08;网友电子白菜撰写&#xff09;》&#xff0c;于是前几天在淘宝上买了一批PCB DIY工具和材料回来&#xff0c;想自己弄个试试&#xff0c;岂料障碍重重&#xff0c;甚至于酿成大祸... 首先是PCB打印的软件设置问题&#xff0c;我…

magento cms page、登錄頁面修改(增加)breadcrumbs

由於magento的cms功能有限&#xff0c;在cms page的角度來看&#xff0c;差不存在cms的category&#xff0c;所以cms page的breadcrumbs只會出現單層的結構&#xff08;HOME->About Us), 要想模仿出分層次的結構&#xff0c;就需要修改cbreadcrumbs了。 修改方法如下&#x…

分享一套非常不错的bootstarp3.0.2响应式模板

2019独角兽企业重金招聘Python工程师标准>>> 这是销量第一的bootstrap 响应式后台管理模板&#xff0c;每套模板都是我用20美金买回来的话不多说&#xff0c;下面是五个模板的演示地址&#xff0c;你看到的&#xff0c;就是你可以下载到的。都是收费模板。 官方演示…

内核配置与编译——编译初体验

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、获取内核源码 第一种是kernel.org的官方版本&#xff0c;第二种是三星移植过的&#xff0c;第三种是X210的移植版本。讲课时使用第三种内核&#xff0c;移植实验使用第二种内核。九鼎配置好的k…

10 个理由让你继续干 IT

1.钱&#xff0c;钱&#xff0c;钱对&#xff0c;我们努力工作就是为了赚钱&#xff0c;而IT专业人士的努力工作的确得到了很好的补偿。报酬不仅仅是好而已&#xff0c;而是非常棒。根据美国劳工部《2010年美国 就业与报酬情况概览》&#xff08;表6&#xff0c;PDF&#xff09…