`
xpp02
  • 浏览: 1047922 次
社区版块
存档分类
最新评论

C11标准委员会成员解读C语言新标准

 
阅读更多

导读:C语言国际标准新的新草案之前已经公布,新标准提高了对C++的兼容性,并将新的特性增加到C语言中。此外支持多线程的功能也受到了开发者的关注,基于ISO/IEC TR 19769:2004规范下支持Unicode,提供更多用于查询浮点数类型特性的宏定义和静态声明功能。根据草案规定,最新发布的标准草案修订了许多特性,支持当前的编译器。(背景:C编程语言的标准化委员会(ISO/IEC JTC1/SC22/WG14)已完成了C标准的主要修订,该标准的早期版本于1999年完成,俗称为“C99”。新标准在去年年底完成,也被称为“C11”。)

本文作者Tom Plum是Plum Hall Inc.的技术工程副总监,也是C11和C++11标准委员会的成员,他在这篇文章里从语言集的atomic操作和线程原语开始探讨了C语言的新特性,在文章末尾还讨论了C11与C++兼容性问题。此外,在本文和它的姊妹篇里,作者还描述了C11的新功能、并发性、安全性和易用性等话题。

并发

C11的标准化了可能运行在多核平台上的多线程程序的语义,使用atomic变量让线程间通信更轻量。

头文件<threads.h>提供宏、类型以及支持多线程的函数。下面是宏、类型和枚举常量的摘要总结:

宏:

  1. thread_local,ONCE_FLAG,TSS_DTOR_ITERATIONScnd_tthrd_t,tss_t,mtx_t,tss_dtor_t,thrd_start_t,once_flag。

通过枚举常量:

  1. mtx_init:mtx_plain,mtx_recursive,mtx_timed。

线程枚举常量:

  1. thrd_timedout,thrd_success,thrd_busy,thrd_error,thrd_nomem。

条件变量的函数:

  1. call_once(once_flag*flag,void(*func)(void));
  2. cnd_broadcast(cnd_t*cond);
  3. cnd_destroy(cnd_t*cond);
  4. cnd_init(cnd_t*cond);
  5. cnd_signal(cnd_t*cond);
  6. cnd_timedwait(cnd_t*restrictcond,mtx_t*restrictmtx,conststructtimespec*restrictts);
  7. cnd_wait(cnd_t*cond,mtx_t*mtx);

互斥函数:

  1. voidmtx_destroy(mtx_t*mtx);
  2. intmtx_init(mtx_t*mtx,inttype);
  3. intmtx_lock(mtx_t*mtx);
  4. intmtx_timedlock(mtx_t*restrictmtx;
  5. conststructtimespec*restrictts);
  6. intmtx_trylock(mtx_t*mtx);
  7. intmtx_unlock(mtx_t*mtx);

线程函数:

  1. intthrd_create(thrd_t*thr,thrd_start_tfunc,void*arg);
  2. thrd_tthrd_current(void);
  3. intthrd_detach(thrd_tthr);
  4. intthrd_equal(thrd_tthr0,thrd_tthr1);
  5. noreturnvoidthrd_exit(intres);
  6. intthrd_join(thrd_tthr,int*res);
  7. intthrd_sleep(conststructtimespec*duration,structtimespec*remaining);
  8. voidthrd_yield(void);

特定于线程的存储功能:

  1. inttss_create(tss_t*key,tss_dtor_tdtor);
  2. voidtss_delete(tss_tkey);
  3. void*tss_get(tss_tkey);
  4. inttss_set(tss_tkey,void*val);

这些标准库函数可能更适合作为易用的API的基础而不是开发平台来使用。例如,使用这些低级库的函数时,很容易造成数据竞争,多个进程会不同步地对同一个位置的数据进行操作。C(和C++)标准允许任何行为,即使会发生争用同一个变量x,哪怕会导致严重的后果。例如,多字节值x可能被一个线程修改部分字节,而另一个线程又会修改别的部分(值撕裂),或者产生一些其它的副作用。

下面一个简单的示例程序,它包含一个数据竞争,其中64位的整数x会同时被两个线程改动。

  1. #include<threads.h>
  2. #include<stdio.h>
  3. #defineN100000
  4. charbuf1[N][99]={0},buf2[N][99]={0};
  5. longlongold1,old2,limit=N;
  6. longlongx=0;
  7. staticvoiddo1(){
  8. longlongo1,o2,n1;
  9. for(longlongi1=1;i1<limit;++i1){
  10. old1=x,x=i1;
  11. o1=old1;o2=old2;
  12. if(o1>0){//xwassetbythisthread
  13. if(o1!=i1-1)
  14. sprintf(buf1[i1],"thread1:o1=%7lld,i1=%7lld,o2=%7lld",
  15. o1,i1,o2);
  16. }else{//xwassetbytheotherthread
  17. n1=x,x=i1;
  18. if(n1<0&&n1>o1)
  19. sprintf(buf1[i1],"thread1:o1=%7lld,i1=%7lld,n1=%7lld",
  20. o1,i1,n1);
  21. }
  22. }
  23. }
  24. staticvoiddo2(){
  25. longlongo1,o2,n2;
  26. for(longlongi2=-1;i2>-limit;--i2){
  27. old2=x,x=i2;
  28. o1=old1;o2=old2;
  29. if(o2<0){//xwassetbythisthread
  30. if(o2!=i2+1)
  31. sprintf(buf2[-i2],"thread2:o2=%7lld,i2=%7lld,o1=%7lld",
  32. o2,i2,o1);
  33. }else{//xwassetbytheotherthread
  34. n2=x,x=i2;
  35. if(n2>0&&n2<o2)
  36. sprintf(buf2[-i2],"thread2:o2=%7lld,i2=%7lld,n2=%7lld",
  37. o2,i2,n2);
  38. }
  39. }
  40. }
  41. intmain(intargc,char*argv[])
  42. {
  43. thrd_tthr1;
  44. thrd_tthr2;
  45. thrd_create(&thr1,do1,0);
  46. thrd_create(&thr2,do2,0);
  47. thrd_join(&thr2,0);
  48. thrd_join(&thr1,0);
  49. for(longlongi=0;i<limit;++i){
  50. if(buf1[i][0]!='\0')
  51. printf("%s\n",buf1[i]);
  52. if(buf2[i][0]!='\0')
  53. printf("%s\n",buf2[i]);
  54. }
  55. return0;
  56. }

如果你的应用已经符合C11的标准,并且将它在一个32位的机器编译过了(在64位机器里long long类型会占用两倍以上的存储周期),你将会看到数据竞争的结果,得到像下面乱码一样的输出:

  1. thread2:o2=-4294947504,i2=-21,o1=19792

传统的解决方案是通过创建一个锁来解决数据竞争。然而,用atomic数据有时会更高效。加载和存储atomic类型循序渐进、始终如一。特别是如果线程1存储了一个值名为x的atomic类型变量,线程2读取该值时则可以看到之前在线程1中运行的所有其它存储(即使是非atomic对象)。(C11和C++11标准还提供其他内存一致性的模型,虽然专家提醒要远离它们。)

新的头文件<stdatomic.h>提供了很多命名类和函数来操作atomic数据的大集。例如,atomic_llong就是一个为操作atomic long long整数的类型。所有的整数类都提供了相似的命名。该标准包括一个ATOMIC_VAR_INIT(n)宏,用来初始化atomic整数,如下:

之前的数据竞争的例子可以通过定义x为一个atomic_llong类型的变量解决。简单地改变一下上述例子中声明x的那行语句:

  1. #include<stdatomic.h>
  2. atomic_llongx=ATOMIC_VAR_INIT(0);

通过使用这样的atomic变量,代码在运行中不会出现任何数据竞争的问题。

注意关键字

C委员会并不希望在用户命名空间里创建新的关键字,每个新的C版本都一直在避免出现不兼容之前版本C程序的问题。相比之下,C++委员会(WG21)更喜欢创造新的关键字,例如:C++11定义一个新的thread_local关键字来指定一个线程的本地静态存储,C11使用_Thread_local来代替,在C11新的头文件<threads.h>中有一个宏定义来提供normal-looking name:

  1. #definethread_local_Thread_local

下面我将假设你已经引入例如适当的头文件,所以我会显示normal-looking name。

thread_local存储类

新thread_local存储类为每个线程提供一个单独的静态存储,并且在线程运行之前初始化。但有没有保障措施来防止你捕获一个thread_local变量的地址,并把它传递给其他线程,然后明确实现(即,不便携/不可移植),每个线程在thread_local都有它自己的errno存储副本。

线程可选

C11已指定为多种特色为可选功能,例如:如果它明确实现了一个名为 _ _STDC_NO_THREADS_ _ 的宏,就不会提供一个头名为<threads.h>的头文件,也不可能在其中定义任何函数。

设计准则

作为通则,WG21委托Bjarne Stroustrup整体设计和进化的责任,不明白的话可以在网上搜索“camel is a horse designed by committee”。然而,有一个WG14和WG21同样遵循的设计原则:不要给任何系统编程语言比我们(C/C++)更高效的机会!

一些与会者(称他们为“A组”)认为atomic数据仍将是一个很少使用的专业性功能,但其他人(称他们为“B组”)认为,atomic数据将成为一个重要的功能,至少会在一种系统编程语言中被应用。

在过去的几十年里,很多更高级别的语言都是基于C语言创建的(Java,C#,ObjectiveC,当然,也包括C++)和C++子集或超集(如D和嵌入式C++)。许多参与WG14和WG21的公司已经决定使用这些语言作为自己的应用的编程语言(称他们为“C组”)。这些公司之所以选择C++作为他们的上层应用程序的语言,通常是因为C足够稳定(或者说是因为WG21控制其标准化),而选择其他语言的公司(称他们为“D组”)通常认为C是他们所使用的高级语言非常重要的基石。

有了这些背景,我可以得出一个C11中atomic进化的理由。C++11中对atomic的设计充分运用了模板。比如atomic<T>是获得任何一种类型T的简单且常用的方法。即使T是一个类或结构,那么无论T*指向哪儿,atomic<T*>都会保存类型信息,但是,几年来,C语言的设计依然只用了几十种命名类型(如上所示的atomic_llong)。这样做的主要优点在于:它不需要编译器做任何改变。它能够实现一个仅库的解决方案,会在最低水平调用系统依赖的原生函数。然而命名类型的解决方案干挠了为C结构或者T*指针创建atomic(无论多么小)。主要因为B组和D组的意见,WG14决定要求C11编译器为任何类型的T识别atomicT。

后来也有一个WG14内部的关于编译器识别atomicT语法的争论。一种使用atomic-parenthesis的解决方案因为和C++良好的兼容性而被推动。Let _Atomic(T)成为了指定atomicT的语法。同样的源程序能够简单地在C++定义宏中编译。

  1. #define_Atomic(T)atomic<T>

另一种相反的观点认为应该创建新的类限制符(类似于C99的_Complex的解决方案);使用"atomic-space"语法,atomic T类型应该被写为“_Atomic T”。使用这种语法的程序型的程序无法立刻被当作C++来编译。(无兼容性宏,本质上看起来像atomic-parenthesis的方法)。

获取C11标准

新标准可以在webstore.ansi.org查看(或者搜索"ISO/IEC 9899:2011")。现在已经有了PDF文档,但是需要支付$285(和C++2011一样)才可以使用。一旦这些标准被ANSI采纳为美国国家标准,价格将下降至$30左右。

你可以定期检查此页面的部分,我及时检查草案的状态,如果您填写了这个Web表单,将会在C11和C++11被ANSI采用为标准时获得电子邮件通知。也可以通过tplum@plumhall.com联系我,非常感谢来自Pete Becker(C++2011标准的项目编辑)的建设性建议。

原文链接:drdobbs.com

更多关于C11的变更可以参考维基百科

(本文为CSDN编译整理,未经允许不得转载。如需转载请联系market@csdn.net)

相关文章:

ISO发布C语言标准新版本

C语言中史上最愚蠢的Bug

如何创建比C语言更快的编程语言?


分享到:
评论

相关推荐

    《C语言最新C11标准》PDF

    C11标准,全称为ISO/IEC 9899:2011,是国际标准化组织(ISO)和国际电工委员会(IEC)共同发布的C语言编程语言的最新规范。这个标准引入了新的特性,提高了程序的安全性和效率,并对原有的语法和库函数进行了修订。 ...

    C语言规范之C11标准

    C语言规范之C11标准是C语言的最新官方版本,由国际标准化组织(ISO)在2011年发布,因此得名C11。这个标准是对C99的更新,引入了一系列新特性,旨在增强C语言的功能性和安全性。在深入探讨C11标准之前,我们首先需要...

    C11标准.pdf

    国际标准化组织(ISO)和国际电工委员会(IEC)负责维护该标准,并鼓励收到该草案的人员提交他们的评论和相关专利通知,同时提供支持文件。 从之前草案N1539的版本中,C11标准所作的更改在文档右侧的边缘处用...

    (0积分)C语言标准(c89,c99,c11,c17,c2x)

    每个标准的发布都伴随着技术委员会的修订和解释文档,例如"n1124"是C99标准的一个版本,包含了技术修订1(TC1)和技术修订2(TC2)。"The rationale for the C99 standard"提供了制定C99标准时的考虑和决策过程,这...

    C11标准.pdf_C语言_OnPurpose_C语言标准_c11标准pdf_c11_

    This International Standard specifies the form and establishes the interpretation of programs expressed in the programming language C. Its purpose is to promote portability

    标准C语言指南-C11标准

    本书基于C语言的最新标准ISO/IEC 9899:2011-C11标准,力求全面地介绍这门计算机语言的各个方面:词法元素、类型、声明、表达式、语句等,全书内容按概念和术语分类组织,示例丰富,查阅方便,适合具有一定C语言基础...

    C99、C11标准新特性解析:现代C语言编程的演进

    C99和C11标准的发布为C语言带来了许多现代化的特性,这些特性不仅提高了编程的灵活性和效率,也使得C语言能够更好地适应新的编程需求。通过理解和掌握这些新特性,开发者可以编写出更加高效、可维护的C代码。

    C11标准及C语言标准(和部分非标准)函数手册

    C11标准及C语言标准(和部分非标准)函数手册

    标准C语言参考手册 C11

    2011年12月8日,ISO正式公布C语言新的国际标准草案:ISO/IEC 9899:2011,即C11 这是最新的C语言参考手册

    C语言编程魔法书:基于C11标准

    C语言编程魔法书:基于C11标准,AZW3格式下载。 C语言编程魔法书:基于C11标准,AZW3格式下载。

    C11标准文档.pdf

    根据提供的文件内容,可以生成关于C11标准文档的知识点,主要包括了C语言标准的介绍、C语言及其标准库的规范、对C程序的环境、执行库内容以及对C程序可移植性、可靠性、可维护性和效率执行的促进。 1. C11标准介绍...

    C标准文档(内含C89/C90,C99,C11标准文档)

    这个压缩包包含了C语言的三个重要版本——C89/C90,C99,C11的标准文档,这些文档是理解C语言规范、编写标准合规代码的关键参考资料。 1. **C89/C90标准**:这是C语言的第一个官方标准,由国际标准化组织(ISO)在...

    C11语言标准

    从技术上讲,C11标准与之前的草案(N1539)相比,新标准在右侧边缘用“diffmarks”标记了变化,用“*”标记删除的文本,用“‘”标记新增或改动的文本。通过这种方式,C11标准对代码的编写和程序的执行提出了更为...

    ISO/IEC 9899:2011 c11 标准 正式版

    ISO/IEC 9899:2011标准,又称C11标准,是ISO(国际标准化组织)和IEC(国际电工委员会)联合制定的C语言的最新标准,正式发布于2011年。C11标准是对1999年发布的C99标准的进一步更新,引入了一些新的功能和改进,以...

    c语言c99标准和C++c++11标准PDF文档

    C99是C语言的第三个官方标准,由国际标准化组织(ISO)和国际电工委员会(IEC)于1999年发布。这个标准对C89(也称为ANSI C)进行了许多更新和扩展,主要包含以下关键点: 1. **类型安全**:引入了`stdint.h`头文件...

    C语言编程魔法书:基于C11标准.mobi

    语法扩展篇(第17~19章)讲述了GCC与Clang编译器对C语言的扩展,以及C语言的设计理念、未来C语言新添与排除特性。需要对底层交互与开发深入了解的读者大有裨益。 项目实践篇(第20~21章),UTF-8与UTF-16编码程序...

    C85/C95/C99/C11/C17 标准帮助文档 2020-09-04

    C85、C95、C99、C11和C17是C语言的不同版本标准,这些标准定义了语言的语法、特性以及程序员应遵循的规则。下面我们将分别探讨这些版本的主要特点和更新内容。 1. C85(通常指的是C89): 这是C语言的第一个正式...

    C11标准-n1570.rar

    2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC) 旗下的C语言标准委员会(ISO/IEC JTC1/SC22/WG14)正式发布了C11标准 。 C11标准的最终定稿的草案是免费开放的,为N1570 ,但是正式标准文件需要198...

    C语言标准文件C99C11英文版.rar

    C99和C11是两个关键的C语言国际标准版本,分别发布于1999年和2011年,由国际标准化组织ISO(International Organization for Standardization)和IEC(International Electrotechnical Commission)联合制定。...

    C语言标准与实现 熟悉了解C语言的标准及其制定内容

    C89/C90是第一个国际标准,由国际标准化组织(ISO)和国际电工委员会(IEC)在1989年发布,1990年正式生效。这个标准奠定了C语言的基础,包括基本数据类型、控制结构、函数、指针、预处理器等核心概念。C99是重要的...

Global site tag (gtag.js) - Google Analytics