ANSI C标准 vs GNU C标准

简介: ANSI C标准 vs GNU C标准

1.ANSI C标准


ANSI C标准被几乎所有广泛使用的编译器所支持,多数C语言代码是在ANSI C基础上写的。记得,大学那会上的《C语言程序设计》课程中讲到的也是这个标准的C语言。


ANSI C是美国国家标准协会(ANSI)对C语言发布的标准,使用C的软件开发者被鼓励遵循ANSI C文档的要求。ANSI C经历了以下的历史过程:


(1).C语言的第一个标准由ANSI发布。虽然这份文档后来被国际标准化组织ISO采纳并且ISO发布的修订版也同样被ANSI采纳。但是,ANSI C却仍然被广泛使用。


(2).C89标准:1983年,美国国家标准协会组成了一个委员会为了创建C语言的一套标准,经过漫长的过程,该标准于1989年完成。因此,这个版本的语言也经常被称为C89标准。

(3).C90及后续标准:在1990年,ANSI C标准有了一些小的改动,这个版本有时候也被、称为C90标准。随着时代的发展,ANSI C标准也在不断与时俱进。出现了C99标准、C11标准等。


2.GNU C标准


GNU计划是由Richard Stallman在1983年9月27日公开发起的。他的目标是创建一套完全自由的操作系统,他在编写linux时自己制作了一个标准即GNU C标准。总体来说,现在linux环境下也支持标准C,因此以后标准C可以跨平台。然而,GUN C标准一般只在linux C环境下应用。


我们在linux环境下编写完一个C语言程序进行编译时,此时会用到GCC编译器。GCC编译器是一套由GNU开发的程序语言编译器。GCC编译器支持C90标准,不完全支持C99标准。在不特别指定C语言标准的情况下,GCC编译器默认符合GNU C标准。GCC 4.7版本的编译器已支持如下4种C语言标准:


1.png


3.两者的差异


其实,我以前学习C语言的时候并没有关心C语言标准相关的知识。最近,在公司看代码时发现了C语言代码中居然有inline关键字,心中在想这家伙不是应该出现在C++代码中吗。于是,网上查了一些资料。首先,对比ANSI C(特指C99标准)与标准C++的差异,具体如下:


(1).ANSI C标准不支持引用、不支持函数重载、不支持命名空间、不包含bool类型,无true和false关键字、不支持标准C++中的变量初始化方式:int a(8);

(2).ANSI C标准声明结构体体时,必须使用struct关键字,而标准C++不需要;(3).ANSI C标准库中的一些头文件在标准C++有了新名称,如cstring、ctime等;
(4).ANSI C不支持内联函数、不支持全局变量作用域解析操作符::;(5).声明函数时,参数列表为空的含义不同。ANSI C中表示接收任意多个数量的参数,而标准C++中表示不接受参数。(6).使用const关键字修饰的全局常量在ANSI C标准中具有外部链接性,而在标准C++中具有内部链接性。


接着,对比GNU C标准与ANSI C标准的差异,具体如下:


(1).GNU C标准支持零长度和变量长度数组


struct var_data {
  int len;
  char data[0];  // 零长度数组
};
int main(int argc, char *argv[]){
  int i, n = argc;
  double x[n];  // 变量长度数组
  return 0;
}


(2).case范围:GNU C支持case x...y这样的语法,区间[x,y]中的数都会满足这个case的条件,如下代码所示:


switch (ch)
{
  case '0' ... '9': c -= '0';       
      break;
  case 'a' .... 'f': c -= 'a' - 10;
      break;
}
/* case '0' ... '9': c -= '0';  等价于ANSI C标准中的case '0': case
 '1': case '2': case '3': case '4':  case '5': case '6':  case '7':  case '8':  case '9': 
*/


(3).语句表达式GNU C把包含在括号中的复合语句看成是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方。可以在语句表达式中使用原本只能在复合语句中使用的循环、局部变量等。如下面代码所示:


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


(4).typeof关键字:typeof(x)语句可以获取x的类型,因此,可以使用typeof重新定义min这个宏。不需要像上面min_t(type,x,y)那样的宏,将type参数传入。因为,通过typeof(x)、typeof(y)可以获取type。代码(void) (&__x == &__y)用于检查__x和__y的类型是否一致,如下代码所示:


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


(5).可变参数宏:ANSI C原先就支持可变参数函数,这表示函数的参数是不固定的。如printf()函数原型为:int printf(const char *format [, argument]......);而GNU C标准中,宏也可以接受可变数量的参数。如下代码所示:


#define pr_debug(fmt, arg......) printk(fmt, ##arg)  // arg表示其余参数,可以有0个或多个参数。##为了处理arg不代表任何参数的情况下,GNU C预处理器就会丢弃前面的逗号


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


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


(7).当前函数名:GNU C预定义了两个标识符保存当前函数的名字,__FUNCTION__即函数在源代码中的名字。__PRETTY_FUNCTION__保存带有语言特色的名字。在C语言的函数中,这两个名字一样的。C99标准中已经支持__func__这个宏。


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

(8).特殊属性声明:GNU C标准允许声明函数、变量和类型的特殊属性,以便于手动优化代码和定制代码检查的方法。要指定一个声明的属性,只需要在声明后添加__attribute__(ATTRIBUTE)。其中,ATTRIBUTE为属性说明,如果存在多个属性,则以逗号分隔开。


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


(9).内建函数:GNU C标准中提供了大量内建函数,其中大部分是ANSI C标准库函数的GNU C编译器内建版本,如memcpy()等,它们与对应的标准C库函数功能相同。不属于库函数的其他内建函数命名通常以__builtin开始,如下代码所示:


#define test_bin(nr, addr) \
(__builtin_constant_p(nr) ? \
constant_test_bit((nr), (addr)) : variable_test_bit((nr), (addr)))
相关文章
|
6月前
|
安全 程序员 编译器
|
1月前
TIA/EIA 568A 和 TIA/EIA-568B 标准详解
【10月更文挑战第14天】
277 0
|
3月前
|
XML 数据格式 索引
GenICam标准(五)
GenICam标准(五)
48 2
|
3月前
|
XML 缓存 安全
GenICam标准(二)
GenICam标准(二)
73 1
|
3月前
|
XML API 数据格式
GenICam标准(一)
GenICam标准(一)
78 1
|
3月前
|
XML 传感器 缓存
GenICam标准(四)
GenICam标准(四)
44 1
|
3月前
|
XML 缓存 编解码
GenICam标准(三)
GenICam标准(三)
45 1
|
3月前
|
API 索引
GenICam标准(六)
GenICam标准(六)
51 0
|
4月前
|
Web App开发 人工智能 前端开发
你想成为什么样的人,你就要以什么样的标准来要求自己
志在成为“前端第一人”,专注Web前端开发,精通HTML/CSS/JS,擅长各浏览器兼容性处理。熟悉Node.js及前端框架如React、Vue。强调团队协作,项目管理和优化,使用Git等工具。热衷新技术,如Vue与MUI结合,自动化工具Webpack、Gulp。具备接口调试和服务器配置能力,曾实现微信支付功能,开发多端商城及大型项目。现致力于AI集成,如ChatGPT和Kimi,运用Python进行数据处理。
42 0
|
API 数据格式
IIIF 标准
IIIF 标准
322 0