前言 - 需要点开头

  C11标准是C语言标准的第三版(2011年由ISO/IEC发布),前一个标准版本是C99标准。

相比C99,C11有哪些变化呢!!所有的测试全部基于能够和标准贴合的特性平台. 但是绝大部

分来源于 GCC. 这里不妨教大家源码安装最新的GCC吧。

a. 首先去 GNU GCC官网下载最新的 GCC 源码

  GCC  : https://gcc.gnu.org/

下载最新源码, 安装过程中可能提示下面这句话

configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.

说白了缺少上面 GMP,MPFR,MPC 三个组件。 那么开始下载

  GMP  : ftp://ftp.gnu.org/gnu/gmp/

  MPFR: http://www.mpfr.org/mpfr-current/

  MPC  : ftp://ftp.gnu.org/gnu/mpc/

b. 开始挨个解压安装 GMP → MPFR → MPC → GCC

开始执行命令跑起来。

cd gmp-6.1.2/mkdir  gmp-6.1.2-build
cd gmp-6.1.2-build
../configure

我们如果出现

checking for suitable m4... configure: error: No usable m4 in $PATH or /usr/5bin (see config.log for reasons).

不用怕,那就继续安装 m4

  m4ftp://ftp.gnu.org/gnu/m4/

cd m4-1.4.18mkdir m4-1.4.18-buildcd m4-1.4.18-build../configuremakesudo make install

那继续安装 GMP。

cd ../../gmp-6.1.2 /gmp-6.1.2-build../configuremakesudo make install

随后就是 MPFR

cd ../../mpfr-3.1.6mkdir mpfr-3.1.6-buildcd mpfr-3.1.6-build../configuremakesudo make install

然后就是 MPC

cd ../../mpc-1.0.3mkdir mpc-1.0.3-buildcd mpc-1.0.3-build../configuremakesudo make install

最后还是回到我们的 gcc

cd ../../gcc-7.2.0mkdir gcc-7.2.0-buildcd gcc-7.2.0-build../configure

又是不好意思,提示下面错误信息

configure: error: I suspect your system does not have 32-bit development libraries (libc and headers). If you have them, rerun configure with --enable-multilib. If you do not have them, and want to build a 64-bit-only compiler, rerun configure with –disable-multilib.

继续

../configure --enable-multilibmake

不好意思又来了

checking dynamic linker characteristics... configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES.
Makefile:11923: recipe for target 'configure-stage1-zlib' failed
make[2]: *** [configure-stage1-zlib] Error 1
make[2]: Leaving directory '/home/wangzhi/桌面/gcc-7.2.0/gcc-7.2.0-build'
Makefile:23803: recipe for target 'stage1-bubble' failed
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory '/home/wangzhi/桌面/gcc-7.2.0/gcc-7.2.0-build'
Makefile:933: recipe for target 'all' failed
make: *** [all] Error 2

没关系我们继续搞,存在首次安装GCC不彻底污染问题,清理后继续安装

make distclean../configure –enable-multilibmake

还是不行更换思路, 走插件全安装

sudo apt-get install gawksudo apt-get install gcc-multilib
sudo apt-get install binutils
sudo apt-get install lzipmake distclean../configuremakesudo make install

见过漫长的等待,下面就是见证历史奇迹的时候了。

到这里关于 GCC 升级到最新版本问题以及搞定。

正文  -  C11标准特性研究

1对齐处理

  alignof(T)返回T的对齐方式,aligned_alloc()以指定字节和对齐方式分配内存,头文件<stdalign.h>

定义了这些内容。我们首先看看 stdalign.h 中定义

/* ISO C1X: 7.15 Alignment <stdalign.h>.  */#ifndef _STDALIGN_H
#define _STDALIGN_H#ifndef __cplusplus#define alignas _Alignas
#define alignof _Alignof#define __alignas_is_defined 1
#define __alignof_is_defined 1#endif#endif    /* stdalign.h */

alignas 设置内存的对其方式, alignof 返回内存的对其方式。

Aligned.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdalign.h>#define _INT_NAME   (128)struct names {int len;char name[];
};struct people {int id;alignas(struct names) char name[sizeof(struct names) + _INT_NAME];
};static void test_aligned(void) {printf("sizeof(struct people) = %zu.\n", sizeof(struct people));// 控制内存布局struct people pe = { 1 };struct names * name = (struct names *)pe.name;name->len = _INT_NAME;strcpy(name->name, "你好吗?");printf("people len = %d, name = %s.\n", pe.id, name->name);// 测试内存对其printf("alignof(struct people) = %zu.\n", alignof(struct people));// 接着控制内存布局alignas(struct names) char xname[sizeof(struct names) + _INT_NAME];struct names * xna = (struct names *)xname;strcpy(xna->name, "我还行!");//// 另一种内存申请, 一种演示, malloc已经够额// aligned_alloc 相比 malloc 多了第一个参数, 这个参数必须是2的幂// 在特定嵌入式平台会使用//
    void * ptr = aligned_alloc(alignof(struct names), _INT_NAME);if (NULL == ptr)exit(EXIT_FAILURE);free(ptr);
}

2 _Noreturn

  _Noreturn是个函数修饰符,位置在函数返回类型的前面,声明函数无返回值,

有点类似于gcc的__attribute__((noreturn)),后者在声明语句尾部。

#include <stdio.h>
#include <stdlib.h>_Noreturn static void _test(void) {puts("func _test C11 never returns");abort();
}int main(int argc, char * argv[]) {_test();
}

3 _Generic

  _Generic支持轻量级范型编程,可以把一组具有不同类型而却有相同功能的函数抽象为一个接口。

#include <stdio.h>void sort_insert_int(int a[], int len);
void sort_insert_float(float a[], int len);
void sort_insert_double(double a[], int len);#define sort_insert(a, len) \_Generic(a, \int *    : sort_insert_int, \float *  : sort_insert_float, \double * : sort_insert_double)(a, len)//
// file     : generic.c
// test     : C11 泛型用法
//
int main(int argc, char * argv[]) {int a[] = { 1, 2, 5, 3, 4, 11, 23, 34, 33, 55, 11, 12 };int i, len = sizeof a / sizeof (*a);sort_insert(a, len);for (i = 0; i < len; ++i)printf("%2d ", a[i]);putchar('\n');return 0;
}#define sort_insert_definition(T) \void \sort_insert_##T (T a[], int len) { \int i, j; \for (i = 1; i < len; ++i) { \T key = a[j = i]; \while (j > 0 && a[j - 1] < key) { \a[j] = a[j - 1]; \--j; \} \a[j] = key; \} \}sort_insert_definition(int)
sort_insert_definition(float)
sort_insert_definition(double)

最终输出结果如下

4 _Static_assert()

  _Static_assert(),静态断言,在编译时刻进行,断言表达式必须是在编译时期可以计算的表达式,

而普通的assert()在运行时刻断言。

#include <stdio.h>int main(void) {printf("C version : %ld.\n", __STDC_VERSION__);_Static_assert(__STDC_VERSION__ < 201112L, "It is c11 version");return 0;
}

其实本质等同于, 真的有点鸡肋

#if __STDC_VERSION__ >= 201112L
#   error "It is c11 version"
#endif

5、安全版本的几个函数

  gets_s()取代了gets(),原因是后者这个I/O函数的实际缓冲区大小不确定,

以至于发生常见的缓冲区溢出攻击,类似的函数还有其它的。

_Success_(return != 0)
_ACRTIMP char* __cdecl gets_s(_Out_writes_z_(_Size) char*   _Buffer,_In_                  rsize_t _Size);

目前在 VS 中有这个函数实现. C11 废弃了 gets, 这里是最接近的 api, 相比 fgets 它不会记录最后一个 '\n'.

并且会在最后一个字符添加 '\0'. 其中 rsize_t 和 size_t 类型是一样的, 但是

#if __STDC_WANT_SECURE_LIB__typedef size_t rsize_t;
#endif#if __STDC_WANT_SECURE_LIB__#ifndef RSIZE_MAX#define RSIZE_MAX (SIZE_MAX >> 1)#endif
#endif

也就是 gets_s 第二参数合法区间就是 [1, RSIZE_MAX], 否则它会什么都不做.

6 fopen() 新模式

  fopen() 增加了新的创建、打开模式“x”,在文件锁中比较常用。类似 POSIX 中的

O_CREAT | O_EXCL. 文件已存在或者无法创建(一般是路径不正确)都会导致 fopen

失败。文件以操作系统支持的独占模式打开。可惜的是当前 CL or GCC 都没有提供支持.

主要原因是 glibc 没有提供支持!

7匿名结构体、联合体。

  例如下面这样, 直接 struct cjson::vs 这种访问. 一种语法层面优化.

struct cjson {struct cjson * next;struct cjson * child;unsigned char type; char * key;     union {char * vs;double vd;};
};

8多线程

  头文件<threads.h>定义了创建和管理线程的函数,新的存储类修饰符_Thread_local限定了变

量不能在多线程之间共享。只能等待 glibc 去支持, 单纯而言可以将 pthread 引入标准线程库.

_Thread_local 等价于线程 pthread_key_t 的私有变量, 不是特别适合不推荐使用.

9 _Atomic类型修饰符和头文件<stdatomic.h>

  原子操作也算是 C11 看着 C++11 急眼了, 直接引入的类型. 把编译器提供的特性纳入标准中.

同样支持的很一般般. 但是可以一用. 展示一种最简单的自旋锁写法:

include <stdatomic.h>// 标记类型, init lock
atomic_flag flag = ATOMIC_FLAG_INIT;// 尝试设置占用(原子操作), try lock
atomic_flag_test_and_set(&flag);// 释放(原子操作), unlock
atomic_flag_clear(&flag);

10、改进的Unicode支持和头文件<uchar.h>

  提供了utf-8和 utf-16, utf-32 字符之间转换. 其中 uchar.h 在 winds 一种实现如下:

//
// uchar.h
//
//      Copyright (c) Microsoft Corporation. All rights reserved.
//

#pragma once
#define _UCHAR#include <corecrt.h>_CRT_BEGIN_C_HEADER#define __STDC_UTF_16__
#define __STDC_UTF_32__typedef unsigned short _Char16_t;
typedef unsigned int _Char32_t;#if !defined __cplusplus || (defined _MSC_VER && _MSC_VER < 1900)typedef unsigned short char16_t;typedef unsigned int char32_t;
#endif_Check_return_ _ACRTIMP size_t __cdecl mbrtoc16(_Out_opt_ char16_t *_Pc16, _In_reads_or_z_opt_(_N) const char *_S, _In_ size_t _N, _Inout_ mbstate_t *_Ps);
_Check_return_ _ACRTIMP size_t __cdecl c16rtomb(_Out_writes_opt_(6) char *_S, _In_ char16_t _C16, _Inout_ mbstate_t *_Ps);_Check_return_ _ACRTIMP size_t __cdecl mbrtoc32(_Out_opt_ char32_t *_Pc32, _In_reads_or_z_opt_(_N) const char *_S, _In_ size_t _N, _Inout_ mbstate_t *_Ps);
_Check_return_ _ACRTIMP size_t __cdecl c32rtomb(_Out_writes_opt_(6) char *_S, _In_ char32_t _C32, _Inout_ mbstate_t *_Ps);_CRT_END_C_HEADER/** Copyright (c) 1992-2013 by P.J. Plauger.  ALL RIGHTS RESERVED.* Consult your license regarding permissions and restrictions.V6.40:0009 */

使用起来也很简单.

#include <stdio.h>
#include <uchar.h>
#include <locale.h>
#include <string.h>//
// uchar test
//
int main(int argc, char * argv[]) {size_t i, len;const char * str = u8"z\u00df\u6c34\U0001F34C"; // 或 u8"zß水?"
setlocale(LC_ALL, "en_US.utf8");len = strlen(str);printf("Processing %zu bytes: [ ", len);for (i = 0; i < len; ++i) {// 强转是画龙点睛之笔printf("0x%x ", (unsigned char)str[i]);    }printf("]\n");size_t rc;char16_t c16;mbstate_t state = { 0 };const char * ptr = str, * end = str + len;/*//// mbrtoc16 : UTF-8 转换为 UTF-16// _Pc16     -     指向将写入产生的 16-bit 宽字符的位置的指针// _S        -     指向用作输入的多字节字符串的指针// _N         -     能检验的字节数上的限制// _Ps         -     指向转译多字节字符串时所用转换状态对象的指针 // return    :    //                若从 s 转换的字符是空字符(并存储于 *pc16 ,若它非空),则为 0 。//                成功从 s 转换的多字节字符的字节数 [1...n] 。//                若下个 char16_t 组成多 char16_t 字符,并已写入 *pc16 ,则为 -3 。此情况下不从输入处理字节。//                若接下来 n 个字符组成不完整,但到此还合法的多字节字符,则为 -2 。不写入 *pc16 。//                若出现编码错误则为 -1 。不写入 *pc16 ,存储值 EILSEQ 于 errno ,且 *ps 状态未指定。 //size_t __cdecl mbrtoc16(char16_t * _Pc16, const char * _S, size_t _N, mbstate_t * _Ps);
*/while ((rc = mbrtoc16(&c16, ptr, end - ptr + 1, &state))) {printf("Next UTF-16 char: 0x%x  obtained from ", c16);if (rc == (size_t)-3)printf("earlier surrogate pair\n");else if (rc <= ((size_t)-1) / 2) {printf("%zu bytes [ ", rc);for (i = 0; i < rc; ++i)printf("0x%x ", (unsigned char)ptr[i]);    printf("]\n");ptr += rc;} else break;}return 0;
}

最终输出结果

11quick_exit()

  又一种终止程序的方式,当exit()失败时用以终止程序。对于退出操作, 目前有这几种

abort -> quick_exit -> exit , abort 直接退出什么都不管. exit 会先执行 atexit 注册的操作,

随后各种额外处理, 刷新缓冲区, 刷新文件描述符. quick_exit 处理流程非常简单, 先执行 at_quick_exit

注册函数随后交给 _exit 直接退出, 但是如果 at_quick_exit 中调用了 exit, 则行为是未定义.

12、复数宏,浮点数宏。

  新的标准添加了创建复数宏, 主要是相对 C99 的, 例如 complex.h 中多了些复数操作

相关的宏

#define complex        _Complex/* Narrowest imaginary unit.  This depends on the floating-pointevaluation method.XXX This probably has to go into a gcc related file.  */
#define _Complex_I    (__extension__ 1.0iF)/* Another more descriptive name is `I'.XXX Once we have the imaginary support switch this to _Imaginary_I.  */
#undef I
#define I _Complex_I#if defined __USE_ISOC11 && __GNUC_PREREQ (4, 7)
/* Macros to expand into expression of specified complex type.  */
# define CMPLX(x, y) __builtin_complex ((double) (x), (double) (y))
# define CMPLXF(x, y) __builtin_complex ((float) (x), (float) (y))
# define CMPLXL(x, y) __builtin_complex ((long double) (x), (long double) (y))
#endif

对于浮点数处理宏多了一些 (More macros for querying the characteristics of floating point types,

concerning subnormal floating point numbers and the number of decimal digits the type is able to store)

上面是摘自 C11 标准中文字, 我们简单的以 GCC 对于 float.h 中一些实现

#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
/* Versions of DECIMAL_DIG for each floating-point type.  */
#undef FLT_DECIMAL_DIG
#undef DBL_DECIMAL_DIG
#undef LDBL_DECIMAL_DIG
#define FLT_DECIMAL_DIG        __FLT_DECIMAL_DIG__
#define DBL_DECIMAL_DIG        __DBL_DECIMAL_DIG__
#define LDBL_DECIMAL_DIG    __DECIMAL_DIG__/* Whether types support subnormal numbers.  */
#undef FLT_HAS_SUBNORM
#undef DBL_HAS_SUBNORM
#undef LDBL_HAS_SUBNORM
#define FLT_HAS_SUBNORM        __FLT_HAS_DENORM__
#define DBL_HAS_SUBNORM        __DBL_HAS_DENORM__
#define LDBL_HAS_SUBNORM    __LDBL_HAS_DENORM__/* Minimum positive values, including subnormals.  */
#undef FLT_TRUE_MIN
#undef DBL_TRUE_MIN
#undef LDBL_TRUE_MIN
#define FLT_TRUE_MIN    __FLT_DENORM_MIN__
#define DBL_TRUE_MIN    __DBL_DENORM_MIN__
#define LDBL_TRUE_MIN    __LDBL_DENORM_MIN__#endif /* C11 */

13、time.h新增timespec结构体,时间单位为纳秒,原来的timeval结构体时间单位为毫秒。

关于这个特别爽, 特别是引入了 timespec_get 谁用谁知道.

#ifndef _CRT_NO_TIME_Tstruct timespec{time_t tv_sec;  // Seconds - >= 0long   tv_nsec; // Nanoseconds - [0, 999999999]
    };
#endif// The number of clock ticks per second
#define CLOCKS_PER_SEC  ((clock_t)1000)#define TIME_UTC 1_Check_return_
static __inline int __CRTDECL timespec_get(_Out_ struct timespec* const _Ts,_In_  int              const _Base)
{return _timespec64_get((struct _timespec64*)_Ts, _Base);
}

不妨写个 demo

#include <stdio.h>
#include <time.h>//
// struct timespec heoo
//
int main(void) {struct tm tm;struct timespec ts;timespec_get(&ts, TIME_UTC);printf("time_t tv_sec = %lld, long   tv_nsec = %d.\n", (long long)ts.tv_sec, ts.tv_nsec);// 线程不安全, 单纯为了测试tm = *localtime(&ts.tv_sec);printf("now %s", asctime(&tm));    return 0;
}        

最终结果

后记  -  一切刚刚开始

  关于 C11标准研究部分就到这里了. 说真的, 新手别入坑.  欢迎指针错误, 最后引述一个大佬的话

转载于:https://www.cnblogs.com/life2refuel/p/7604655.html

C11 标准特性研究相关推荐

  1. C/C++ 之 C发展史及 各标准特性说明

    Tips:  1. 本人当初学习C/C++的记录.  2. 资源很多都是来自网上的,如有版权请及时告知!  3. 可能会有些错误.如果看到,希望能指出,以此共勉! C 发展史   1951年,IBM的 ...

  2. 《C语言编程魔法书:基于C11标准》——第一篇 预备知识篇 第1章 C魔法概览1.1 例说编程语言...

    本节书摘来自华章计算机<C语言编程魔法书:基于C11标准>一书中的第1章,第1.1节,作者: 陈轶 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第一篇 预备 ...

  3. 《C语言编程魔法书:基于C11标准》——1.3 主流C语言编译器介绍

    本节书摘来自华章计算机<C语言编程魔法书:基于C11标准>一书中的第1章,第1.3节,作者: 陈轶 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1.3 主流 ...

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

    导读:C语言国际标准新的新草案之前已经公布,新标准提高了对C++的兼容性,并将新的特性增加到C语言中.此外支持多线程的功能也受到了开发者的关注,基于ISO/IEC TR 19769:2004规范下支持 ...

  5. ANSI、C99、C11 标准区别详解

    一.ANSI C 标准 美国国家标准协会(ANSI)为创立 C 语言的一套标准,于 1989 年完成,因此常被称为 C89. 在 KEIL 中使用的是 ANSIC C 标准(C89 标准),定义变量一 ...

  6. c语言魔法书,C语言编程魔法书:基于C11标准

    C语言编程魔法书:基于C11标准 作者:陈轶 著 出版日期:2017年05月 文件大小:10.29M 支持设备: ¥60.00在线试读 适用客户端: 言商书局 iPad/iPhone客户端:下载 An ...

  7. c语言程序设计资料书下载,C语言编程魔法书:基于C11标准 (陈轶著) 完整pdf高清版[20MB]...

    C语言编程魔法书:基于C11标准主要讲解C11标准的语法内容,并且从整个编译.连接到加载过程都会涉及.同时在后会分别介绍GCC编译器与Clang编译器的C语言语法扩展.通过阅读本书,读者能够完全掌握新 ...

  8. c语言c11标准用得多吗,C语言的C11 标准有哪些改进的地方?C11 为何不如 C++11 流行?...

    1.   C语言的C11 标准有哪些改进的地方?会对各类C项目起到哪些帮助? 1. 对齐处理操作符 alignof,函数 aligned_alloc(),以及 头文件 . 2. _Noreturn 函 ...

  9. 传感与检测技术,光电二极管和光敏电阻的特性研究实验报告,江南大学物联网工程学院自动化

    江南大学物联网工程学院传感与检测技术<光电二极管和光敏电阻的特性研究实验报告>分享,包括实验目的.实验仪器设备.实验原理及数据分析和思考与总结.仅供参考借鉴.

最新文章

  1. Python Qt GUI设计:信号与槽的使用方法(基础篇—7)
  2. Quorum-based voting
  3. 小型电商服务器平台搭建(一)
  4. linux yum list包数量少,Linux基础知识之YUM包管理工具
  5. python项目开发实战网盘-《Python项目案例开发从入门到实战》PDF版百度网盘
  6. 正则表达式快速入门,转载
  7. 获取打开文件的路径和文件名
  8. Oracle用rowid删除同一张表的重复记录
  9. JavaScript就这么回事 (JS基础知识整理)
  10. 一分钟了解光纤、单模光纤、多模光纤
  11. c语言随机摇号程序,再谈电脑摇号之作弊
  12. [分块]Most Influential Pumpkin
  13. 微型计算机硬件包括啥,微型计算机系统的硬件包括哪五大组成部分
  14. 使用imagemagic生成动态图片GIF
  15. win10输入法不能切换_怎么解决win10系统微软输入法打不出汉字
  16. 使用nginx搭建音视频点播服务——基于DASH协议
  17. 6. 批量处理分析数据
  18. Datawhale-数据分析-泰坦尼克-第一单元
  19. APP - APP监控软件,美团 24 小时不间断定位上热搜
  20. R语言使用quantmod包的getSymbols函数从指定金融数据源获取指定时间段的股票数据、对股票进行除权除息调整

热门文章

  1. kdevelop快捷键
  2. linux后台挂起、恢复进程相关命令
  3. SpringBoot 日志文件
  4. NLP标注工具Brat的简单使用
  5. 关于Stream()和Collectors.joining()字符串连接器
  6. 关于ffmpeg如何下载、安装和使用
  7. python timer详解_python线程定时器Timer实现原理解析
  8. AD中出现off grid pin问题的解决方法
  9. node.js 基础(含mongodb,express,express-art-template)
  10. 权限管理系统(包括审批流程)数据库设计图