概述 – C语言老矣

Swift语言是一个初的编程语言,用于iOS, macOS, watchOS, 和
tvOS的支出,不过Swift很多有的内容,我们可从C或者Objective-C的开支经历获取同种植熟悉感。Swift提供多基础项目,如Int,String,Double,Bool等种类,它和Objective-C的相关品种对应,不过他是值类型,而Objective-C的基础项目是引用类型,另外Swift还提供了几只聚众类型,如ArraySet,
和 Dictionary;Swift引入一些Objective-C里面没有的元祖类型,这个在C#里倒是有类似的,也是这个名词。 Swift语言是一种类型安全的强类型语言,不是类似JavaScript的弱类型,能够在提供开发效率的同时,减少常规出错的可能,使我们在开发阶段尽量发现一些类型转换的错误并及时处理。

  时而言(2017年5月12日) C语言中生出 32 + 5 + 7 = 44 独重点字. 具体如下
O(∩_∩)O哈哈~

常量和变量

let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0

 常量用let定义,变量用var定义,它们都可以通过自动推导类型,如上面的就是是点名为整形的种。

也足以由此逗号分开多只概念,如下所示

var x = 0.0, y = 0.0, z = 0.0

 如果我们的变量没有初始化值来确定她的类别,我们可以通过点名项目来定义变量,如下所示

var welcomeMessage: String

var red, green, blue: Double

 变量的打印,可以当输出字符串中用括号包含变量输出,括号前加斜杠 \
符号。

print(friendlyWelcome)
// Prints "Bonjour!"

print("The current value of friendlyWelcome is \(friendlyWelcome)")
// Prints "The current value of friendlyWelcome is Bonjour!"

 

-> C89关键字

注释符

// This is a comment.

/* This is also a comment
 but is written over multiple lines. */

/* This is the start of the first multiline comment.
 /* This is the second, nested multiline comment. */
 This is the end of the first multiline comment. */

 上面分别是正规的之注解,以及Swift支持嵌套的笺注符号

 

char short int unsigned
long float double struct
union void enum signed
const volatile typedef auto
register static extern break
case continue default do
else for goto if
return switch while sizeof

分号

Swift语句之撤并可以免用分号,不过你加分号也得,如果加分号,则可以基本上长条告句子放在一行。

let cat = "🐱"; print(cat)

 

-> C99初添关键字

整型

let minValue = UInt8.min  // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max  // maxValue is equal to 255, and is of type UInt8

貌似情形下,我们不待指定具体的Int类型,如Int32,Int64,我们一般下int类型即可,这样可当不同的网平台发生不同的意义。

在32位平台,Int代表是Int32

在64位平台,Int代表Int64

 

_Bool _Complex _Imaginary inline restrict

浮点数字

Swift的浮点数字型包括有Float(单精度)和Double(双精度)两只品类,Float代表32各项浮点数字,Double代表64各浮点数字。

默认通过微数值推导的变量或者常量的路是Double,而非Float。

 

-> C11初长关键字

数字文字

let decimalInteger = 17
let binaryInteger = 0b10001       // 17 二进制
let octalInteger = 0o21           // 17 八进制
let hexadecimalInteger = 0x11     // 17 十六进制

 

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1  //科学计数法 1.21875*10
let hexadecimalDouble = 0xC.3p0 // p0代表 2的0次方

 上面是是计数方式的几乎栽办法

 

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

 上面是运0代替补齐签名数字,以及下划线来标识数字分割,方便阅读

 

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine

 常量 three 初始化位整形类型, pointOneFourOneFiveNine
推导为Double类型,而pi则透过Double转换推导为Double类型,这样右边两个都是Double类型,可以进行相加的演算处理了。

 

_Alignas _Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local

布尔种

let orangesAreOrange = true
let turnipsAreDelicious = false

 这个没什么好讲的,就是言语默认有布尔档次提供,相对于Objective-C的非0则也True而言,布尔项目只有简单单字,True或者False。

布尔色可以用来规范判断等拍卖,如下

if turnipsAreDelicious {
    print("Mmm, tasty turnips!")
} else {
    print("Eww, turnips are horrible.")
}

 

 下面容我细细分析由具体用法.(存在平台差异, 有题目专门欢迎评论上,
这即相当给一个第一字字典)

元祖类型

元祖类型就是构成多个价的一个靶类型,在成中之路可以是其余Swift的档次,而且不要有的价值吗同类别。

let http404Error = (404, "Not Found")
// http404Error is of type (Int, String), and equals (404, "Not Found")

 另外可以解构对应之元祖类型的价值到相应的常量或者变量里面,如下代码

let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// Prints "The status code is 404"
print("The status message is \(statusMessage)")
// Prints "The status message is Not Found"

 也得以由此下划线来忽略相关的值,如下

let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")

 元祖对象中的价好透过数字索引来引用,如0,1的性质,如下

print("The status code is \(http404Error.0)")
// Prints "The status code is 404"
print("The status message is \(http404Error.1)")
// Prints "The status message is Not Found"

 

 

只是空类型

这个和C#里的可空类型是对应之,也就是是目标或出价,也可能无价值

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber 推导类型为 "Int?", 或者 "optional Int"

Int类型的构造函数为可空构造函数,有或移失败,因此归的吗可空Int类型

而是空类型可以由此设置nil,来装它呢无值状态

var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value

 对于可空类型,如果承认它们的值非空,那么可以强行解构它的值对象,访问它的价值当变量后面加一个!符号,如下所示

if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}

 一般情形下,我们得以经可空绑定的办法来拍卖这种对象的价,语句语法如下所示

if let constantName = someOptional {
    statements
}

 具体的言辞如下所示

if let actualNumber = Int(possibleNumber) {
    print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
    print("\"\(possibleNumber)\" could not be converted to an integer")
}
// Prints ""123" has an integer value of 123"

 也堪多单let的可空绑定语句一起使用

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100"

if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}
// Prints "4 < 42 < 100"

 

解包可空类型可以通过!符号进行拍卖,一般情况如下所示进行判定

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // no need for an exclamation mark

 也可采取可空绑定的let 语句进行隐式的解包,如下所示

if let definiteString = assumedString {
    print(definiteString)
}
// Prints "An implicitly unwrapped optional string."

 

C89 32个关键**

错误处理

函数抛来十分,通过在函数里面用throws进行宣示,如下

func canThrowAnError() throws {
    // this function may or may not throw an error
}

 捕捉函数抛来的生代码如下

do {
    try canThrowAnError()
    // no error was thrown
} catch {
    // an error was thrown
}

 详细的案例代码如下所示

func makeASandwich() throws {
    // ...
}

do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

 

1) char

预言调试

Swift提供一些规范库函数来开展预言调试,分为断言和预设标准的拍卖两有的。

预言调试仅仅以Debug调试模式运行,而优先设标准虽是调试模式和活发布后还见面运行的。

let age = -3
assert(age >= 0, "A person's age can't be less than zero.")
// This assertion fails because -3 is not >= 0.

 

if age > 10 {
    print("You can ride the roller-coaster or the ferris wheel.")
} else if age > 0 {
    print("You can ride the ferris wheel.")
} else {
    assertionFailure("A person's age can't be less than zero.")
}

 预设标准代码如下,用来对有些法进行校验

// In the implementation of a subscript...
precondition(index > 0, "Index must be greater than zero.")

 

解释:

  声明变量的时光用! char占1字节, 8bit. 多数网(vs or
gcc)上是出记号的(arm 上无符号), 范围是[-128, 127]. 

在工程项目开发中推介用 

#include <stdint.h>

int8_t   -> signed char 
uint8_t  -> unsigned char

拉一点, 程序开发最常遇到的哪怕是于说问题. 鸡生蛋, 蛋生鸡. 后面再分析
signed 和 unsigned

演示:

#include <stdio.h>

char c;
c = getchar();
rewind(stdin);
printf("c = %d, c = %c.\n", c);

 

2) short

解释:

  声明变量的下用! short 占2字节, 为无符号的. 默认自带signed.
范围[-2^15, 2^15 – 1] 2^15 = 32800.

推荐用 int16_t or uint16_t 类型.

演示:

short port = 8080;
printf("port = %d.\n", port);

 

3) int

解释:

  声明变量的早晚用! int 声明的变量, 占4字节, 有标志. 范围 [-2^31,
2^31-1].

推荐用 int32_t 和 uint32_t类型开发. 方便移植

演示:

int hoge = 24;
printf("hoge = %d.\n", hoge);

 

4) unsigned

解释:

  变量类型修饰符! 被修饰的变量就是无符号的.范围 >= 0.  unsigned
只能修饰整型的变量.

本来当你用这修饰变量的时候. 再以 – 和 — 运算的上势必要小心

演示:

unsigned int i = 0;          // 正确
unsigned short s = 0;        // 正确
unisgned float f = 0.11f;    // 错误

 

5) long

解释:

  声明变量的时段用!长整型 x86达成四字节, x64达8字节.
一定非比较int字节数少.  C99随后出现long long类型8配节.

演示:

    long l = 4;
    long long ll = l;
    printf("l = %ld, ll = %lld.\n", l, ll);

 

6) float

解释:

  声明变量的时用! 四配节. 精度是6-7号左右.  详细精度可以看 float与double的界定以及精度

演示:

float f = -0.12f;        // 四字节
long float lf = 0;       // 八字节 等同于 double, 不推荐这么写

 

7) double

解释:

  声明变量的时刻用!八字节,精度在15-16位左右.组成部分上压缩内存用float代替.

演示:

double d = 2e13;               // 8字节
long double ld = -0.99;        // x86也是8字节, 不推荐这么用
long long double lld = 99;     // 写法错误, 不支持

 

8) struct

解释:

  定义结构体, 这个要字用法广泛, 是大头. c
的机要思路就是面向过程编程. 撑起面向过程的花边就是组织体.

struct 就是概念结构的事物, 可以望下面演示

演示:

// 普通结构体定义
struct node {
    int id;
    struct node * next;   
};

struct node node = { 1, NULL };

// 匿名结构定义
struct {
   int id;
   char * name;   
} per = { 2, "王志" };

 

9) union

解释:

  定义公用体, 用法特别费哨. 常在非常规库函数封装中因故到.技巧性强

演示:

// 普通定义
union type {
    char c;
    int i;
    float f;
};

union type t = { .f = 3.33f };

// 匿名定义
union { ... } t = { .... };

// 类型匿名定义
struct cjson {
    struct cjson * next;     // 采用链表结构处理, 放弃二叉树结构, 优化内存
    struct cjson * child;    // type == ( _CJSON_ARRAY or _CJSON_OBJECT ) 那么 child 就不为空

    unsigned char type;      // 数据类型和方式定义, 一个美好的意愿
    char * key;       // json内容那块的 key名称     
    union {
        char * vs;    // type == _CJSON_STRING, 是一个字符串     
        double vd;    // type == _CJSON_NUMBER, 是一个num值, ((int)c->vd) 转成int 或 bool
    };
};

再度来平等种 union用法, 利用内存对齐. 

//12.0 判断是大端序还是小端序,大端序返回true
inline bool
sh_isbig(void) {
    static union {
        unsigned short _s;
        unsigned char _c;
    } _u = { 1 };
    return _u._c == 0;
}

还有很久以前利用union 实现内存字节对一头, 太多了. 每个重点字用法,
确实很多, 很意外.

 

10) void

解释:

  这个是空关键字. 用法大多. 也是自己尽欣赏的根本字. 用当函数声明遭,
类型定义中.

演示:

// 函数声明
extern void foo();

// 函数参数约束
extern void foo(void);   // ()中加了void表示函数是无参的, 否则是任意的

// 万能类型定义, 指针随便转
void * arg = NULL;

 

11) enum

解释:

  枚举类型, C中枚举类型很简陋. 其实就一定给同种植变相的INT宏常量.
估计就或也是 INT宏常量和枚举并存的原因.

演示:

//
// flag_e - 全局操作基本行为返回的枚举, 用于判断返回值状态的状态码
// >= 0 标识 Success状态, < 0 标识 Error状态
//
typedef enum {
    Success_Exist    = +2,           //希望存在,设置之前已经存在了.
    Success_Close    = +1,           //文件描述符读取关闭, 读取完毕也会返回这个
    Success_Base     = +0,           //结果正确的返回宏

    Error_Base       = -1,           //错误基类型, 所有错误都可用它, 在不清楚的情况下
    Error_Param      = -2,           //调用的参数错误
    Error_Alloc      = -3,           //内存分配错误
    Error_Fd         = -4,           //文件打开失败
} flag_e;

枚举变量完全可一如既往于 int 变量使用, 枚举值等同于宏INT常量使用.
枚举的默认值是为1位单位从上向下递增.

 

12) signed

解释:

  变量声明类型修饰符. 有符号型, 对比 unsigned 无符号型.
变量声明默认基本都是 signed, 所以多数人家就是大概了.

演示:

signed int piyo = 0x1314520;
signed char * str = u8"你好吗";

自矣, 平时不需要着意加. 会叫丁头痛麻烦. O(∩_∩)O哈哈~

 

13) const

解释:

  const修饰的变量表示是单不足修改的量. 和常量有点区别. 可以略认为
const type val 是个单读的.

演示:

// 声明不可修改的量
const int age = 24;

// 修饰指针
const int * pi = NULL;         // *pi 不能修改指向变量
int * const pt = NULL;         // pt 不能指向新的指针 
const int * const pc = NULL;   // *pc 和 pc 都不能动

实则以c中着力无什么改变不了之. 全是内存来回折腾, 软件大硬件~~

 

14) volatile

解释:

  声明变量修饰符, 可变的. 当变量前面来这个修饰符.
编译器不再从寄存器中取值, 直接内存读取写入. 保证实时性.

常用在多线程代码中.

演示:

// 具体轮询器
struct srl {
    mq_t mq;                 // 消息队列
    pthread_t th;            // 具体奔跑的线程
    die_f run;               // 每个消息都会调用 run(pop())
    volatile bool loop;      // true表示还在继续 
};

今后用loop的时刻, 其它线程修改, 当前线程也会是获取其的值.

 

15) typedef

解释:

  类型重定义修饰符. 重新定义新的类型.

演示:

// 声明普通类型
typedef void * list_t;

// 声明不完全类型, 头文件中不存在struct tree
typedef struct tree * tree_t;

 

16) auto

解释:

  变量类型声明符, auto变量存放于动态存储区,随着生命周期{开始
}结束而立即释放.存放在栈上. 

默认变量都是auto的. 基本都是勿写, 除非装逼!

演示:

{
    // 生存期开始
    int hoge = 0;
    auto int piyo = 1;
    // 生存期结束
}

绝不就此生命周期结束的变量, 存在各种意外. 

 

17) register

解释:

  变量修饰符,只能修饰整形变量.表示愿意之变量存放于CPU的寄存器上.现代编译器在开启优化时候,

能够肯定水准达到默认启用register寄存器变量.

演示:

#include <limits.h>

register int i = 0;
while (i < INT_MAX) {

   ++i;
}

出于CPU寄存器是有限的, 有时候你不怕声明的寄存器变量也可能只是一般变量.
printf(“&i = %p\n”, &i) 这种用法是非法.

寄存器变量不可知得到地址.

 

18) static

解释:

  static 用法大广泛. 修饰变量, 表示变量是为静态区, 基本就是是大局区.
生存周期与系统在周期.

static修饰的变量作用域只能当脚下文件范围内. 可以看作上层语言的private.
除了auto就是static.

static修饰函数表示即函数是私房的,只能于眼前文件被利用.
更加详细的看演示部分.

演示:

// 修饰全局变量, 只对当前文件可见
static int _fd = 0;

// 修饰局部变量, 存储在全局区, 具有记忆功能
{
    static int _cnt = 0;
}

// 修饰函数, 函数只能在当前文件可见
static void * _run(void * arg) {
   ......
   return arg;
}

//
// C99之后加的static新用法, 编译器优化
// static 只能修饰函数第一维,表示数组最小长度, 方便编译器一下取出所有内存进行优化
//
int sum(int a[static 10]) { ... }

 

19) extern

解释:

  extern 关键字表示声明, 变量声明, 函数声明.  奇葩的用法很多.

演示:

// 声明引用全局变量
extern int g_cnt;

// 声明引用全局函数
extern int kill(int sig, int val);

本来有时候extern不写, 对于变量不行会面世重定义. 对于函数是足以少省写法.
再扯淡一点

// extern 主动声明, 希望外部可以调用
extern int kill(int sig, int val);

// extern 缺省,不推荐外部调用
int kill(int sig, int val);

 

20) break

解释:

  结束语句. 主要用以循环的跳转, 只能过反至当前层级. 也用于switch
语词被, 跳出switch嵌套.

演示:

for(;;) {
   // 符合条件跳转
   if(six == 6)    
       break;
}


// break 跳出while循环
int i = 0;
while(i < 6) {
   if(i == 3)
      break;
} 

break用法主要与巡回一片用, 还有do while. 但不得不过转当前层循环. 

 

21) case

解释:

  switch 语句中分支语句. 确定走啊分支.

演示:

// case 普通用法 和 break成对出现
switch ((c = *++ptr)) {
case 'b': *nptr++ = '\b'; break;
case 'f': *nptr++ = '\f'; break;
case 'n': *nptr++ = '\n'; break;
case 'r': *nptr++ = '\r'; break;
case 't': *nptr++ = '\t'; break;
}

多扯一点, 对于case相当给标记点. switch
中值决定case跳反到哪里.再一直往生实行, 遇到break再结switch嵌套.

 

22) continue

解释:

  跳了此次循环. 直接开展规范判断操作. for 和 while 有若干局别. for
会执行第三只后面的语句.

演示:

// for 循环 continue
for(int i = 0; i < 20; ++i) {
    if(i % 2 == 0)
         continue;

     // 上面continue 调到 ++i -> i < 20 代码块
}

 

23) default

解释:

  switch 分支的默认分支, 假如case都没有进那就算进入default分支.
default 可以概括break. c 语法中可行.

演示:

uint32_t 
skynet_queryname(struct skynet_context * context, const char * name) {
    switch(name[0]) {
    case ':':
        return strtoul(name+1,NULL,16);
    case '.':
        return skynet_handle_findname(name + 1);
    default:
        skynet_error(context, "Don't support query global name %s",name);    
    }
    return 0;
}

 

24) do

解释:

  do 循环. 先实行循环体, 后复履行尺度判断.

演示:

register i = 0;
do {
    if(i % 2 == 0) 
           continue;

    printf("i = %d.\n", i);   

} while(++i < 10);

do while 循环有时候可减去一浅口径判断. 性能再好, 代码更长.

 

25) else

解释:

  else 是 if 的反分支. 具体看演示

演示:

#include <stdbool.h>

if(true) {
   puts("你好吗?");
}
else {
  puts("我们分手吧.");
}



// 附赠个else 语法
#if defined(__GNUC__)

// 定义了 __GNUC__ 环境, 就是gcc环境

#else

#error "NOT __GNUC__, NEED GCC!";

#enfif

 

26) for

解释:

  for 循环其实就是while循环的语法糖. 也生独树一帜的地方.

演示:

for(int i = 0; i < 2; ++i) {
    if(i == 1)
       continue;
    if(i == 2)
       break;
}

等价于下面这个
int i = 0;
while(i < 2) {
  if(i == 1) {
     ++i;
     continue;
  }
  if(i == 2)
     break;  

  ++i;
}

// for 最好的写法, 在于死循环写法
for(;;) {
   // xxxx
}

for(;;) {  } 比 while(true) { } 写法好, 有同样种不动条件判断的用意,
虽然汇编代码是同的.

 

27) goto

解释:

  goto 是自己第二欣赏的显要字.  可以当时函数内逾转. goto
可以取代有循环.

演示:

__loop:
   // xxx 死循环用法
goto __loop;
__exitloop:

还有就是是以工程支出被, goto 常用于复制的政工逻辑.

    if ((n = *tar) == '\0') // 判断下一个字符
        goto __err_ext;    

    if(cl % rl){ // 检测 , 号是个数是否正常
    __err_ext:
        SL_WARNING("now csv file is illegal! c = %d, n = %d, cl = %d, rl = %d."
            , c, n, cl, rl);
        return false;
    }

 

28) if

解释:

  if 分支语句. 用法太多矣. 程序报句被分就是智能.

演示:

if(false) {
   puts("我想做个好人!");
}

 

29) return

解释:

  程序返回语句极多矣. 用于函数返回中. 返回void 直接 return;

演示:

#include <stdlib.h>

int main(int argc, char * argv[]) {

   return EXIT_SUCCESS;
}

 

30) switch

解释: 

  条件分支语句. 很复杂的if else if 时候可switch.

演示:

#include <unistd.h>

do {
    int rt = write(fd, buf, sizeof buf)
    if(rt < 0) {
       switch(errno) {
       case EINTER
           continue;
       default:
           perror("write error");
       }
    }
} while(rt > 0);

 

31) while

解释:

  循环语句, 有do while 和 while 语句子简单种.

演示:

#define _INT_CNT (10)

int i = -1;
while(++i < _INT_CNT) {
     // ...... 
}

 

32) sizeof

解释:

  这个重中之重字呢叫做 sizeof 运算符. 计算变量或项目的字节大小.
这个首要字特别好用!

演示:

sizeof (main)   -> x86 上四字节

// 获取数组长度,只能是数组类型或""字符串常量,后者包含'\0'
#define LEN(arr) (sizeof(arr) / sizeof(*(arr))) 

顶此地C89保留的根本字基本解释了毕.

 

C99 5个新添关键**

33) _Bool

解释:

  bool类型变量, 等价于 unsigned char . 只有0和1.

演示:

#include <stdbool.h>

bool flag = true;

// 或者直接用
_Bool flag = !0;

 

34) _Complex

解释:

  对于C99 标准定义, 存在 float _Complex, double _Complex, long
double _Complex 复数类型. 下面先演示gcc 中关于复数的之所以法.

演示:

#include <math.h>
#include <stdio.h>
#include <complex.h>

//
// 测试 c99 complex 复数
//
int main(int argc, char * argv[]) {

    float complex f = -1.0f + 1.0if;
    printf("The complex number is: %f + %fi\n",crealf(f), cimagf(f));

    double complex d = csqrt(4.0 + 4.0i);
    printf("d = %lf + %lfi\n", creal(d), cimag(d));

    return 0;
}

实际当复数类型受到, gcc标准落实

#define complex         _Complex

假使当VS 中实现具体也

#ifndef _C_COMPLEX_T
    #define _C_COMPLEX_T
    typedef struct _C_double_complex
    {
        double _Val[2];
    } _C_double_complex;

    typedef struct _C_float_complex
    {
        float _Val[2];
    } _C_float_complex;

    typedef struct _C_ldouble_complex
    {
        long double _Val[2];
    } _C_ldouble_complex;
#endif

typedef _C_double_complex  _Dcomplex;
typedef _C_float_complex   _Fcomplex;
typedef _C_ldouble_complex _Lcomplex;

说到底的而言, 学习C 最好之阳台就是 *nix 平台及使用 Best new GCC.
当然除了科学计算会用到复数, 其它很少.

此间VS 和 GCC实现非一样. 用起来用注意.

 

35) _Imaginary

解释:

  虚数类型. _Complex 复数类型的虚部. 例如 10.0i, 10.8if 等等. 
这个关键字在VS 上未曾兑现. 其实我也当无必要.

和_Complex有重叠.

演示:

  这个主要字无法以代码中表示. 系统保留, 我们无能够使用.

 

36) inline

解释:

  内联函数,从C++中引入的概念. 就是将小函数直接坐到代码中.
C的代码损耗在于函数的出入栈. 要是可以引进用外联函数

代表宏. 宏能不用就无用. 函数声明的时段不要加inline 需要加extern,
定义之时节用加inline.

演示:

/*
 * 对json字符串解析返回解析后的结果
 * jstr        : 待解析的字符串
 */
extern cjson_t cjson_newtstr(tstr_t str);


inline cjson_t 
cjson_newtstr(tstr_t str) {
    str->len = _cjson_mini(str->str);
    return _cjson_parse(str->str);
}


// 还有就是和static 一起使用
static inline int _sconf_acmp(tstr_t tstr, struct sconf * rnode) {
    return strcmp(tstr->str, rnode->key);
}

37) restrict

解释:

  这是大装逼的要害字用于编译器优化. 关键字restrict只用于限定指针;该要字用于告知编译器,

备修改该指针所倚为内容的操作全部都是基于(base
on)该指针的,即不存任何进行改动操作的途径;

如此这般的结局是支援编译器进行重新好之代码优化,生成更有效率的汇编代码。

演示:

extern void *mempcpy (void *__restrict __dest,
                      const void *__restrict __src, size_t __n)
     __THROW __nonnull ((1, 2));

点是择自GCC 的 string.h中. 其实正式用法

// 简单演示用法, GCC 和 VS 都是 __restrict 推荐加在 * 后面
static void _strlove(char * __restrict dest) {
    *dest = '\0';
}

Pelles C 编译器可以整体支持 restrict.

 

C11 7单新增加关键字

38) _Alignas

解释:

  内存对联合的操作符. 需要与_Alignof相当下,
指定结构的指向齐方式.
演示:

#ifndef __cplusplus

#define alignas _Alignas
#define alignof _Alignof

#define __alignas_is_defined 1
#define __alignof_is_defined 1

#endif

像一种用法

#include <stdio.h>
#include <stdalign.h>

struct per {
    int age;
    double secl;
    char sex;
};

int main(int argc, char * argv[]) {
    char c[100];
    alignas(struct per) struct per * per = (struct per *)&c;
    printf("per = %p, c = %p.\n", per, c); 

    return 0;
}

 

将c 数组因为 struct per 对齐方式对共同返回回去.

 

39) _Alignof

解释:

  得到类型以及变量的针对齐方式.
演示:

printf("alignof(struct per) = %zd.\n", alignof(struct per));

 

40) _Atomic

解释:

  原子操作, 原子锁. gcc 很已经支持. 详细用法可以参见 CAS
https://sanwen8.cn/p/18dZQie.html

谈的可以.
演示:

#include <stdio.h>
#include <stdatomic.h>

int main(int argc, char * argv[]) {

    _Atomic int hoge = ATOMIC_VAR_INIT(100);
    int piyo = atomic_load(&hoge);  
    printf("piyo = %d.\n", piyo);
    piyo += 2;
    atomic_store(&hoge, piyo);
    printf("hoge = %d.\n", hoge);

    return 0;
}

实际的推行结果, 你啊掌握就那么样. 原子操作, 对于刻画起快速代码很重要.

 

41) _Generic

解释:

  这个于叼, C的泛函机制. 高级函数宏. 下面来单老套路用法
演示:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define ABS(x) \
        _Generic((x), int:abs, float:fabsf, double:fabs)(x)

//
// 测试 C11 语法
//
int main(int argc, char * argv[]) {

        int a = 1, b = 2, c = 3;

        _Generic(a + 0.1f, int:b, float:c, default:a)++;
        printf("a = %d, b = %d, c = %d\n", a, b, c); 

        printf("int abs: %d\n", ABS(-12));
        printf("float abs: %f\n", ABS(-12.04f));
        printf("double abs: %f\n", ABS(-13.09876));

        return EXIT_SUCCESS;
}

宏泛型真的坏受力. 宏以会玩上天了.

   

42) _Noreturn

解释:

  修饰函数,绝对免见面时有发生归值. _Noreturn 声明的函数不见面返回回.
引入这新的函数修饰符有零星单目的:

  • 排除编译器对无 return的函数的警告. 
  • 允许某种只对无回去函数的优化.

演示:

_Noreturn void suicide(void) {
    abort(); // Actually, abort is _Noreturn as well
}

再度扯淡一点, GCC中等同于 __attribute__((__noreturn__)),
在VC中一般功能是 __declspec(noreturn).

它们不是说函数没有回到值,而是说如而调了这函数,它世代不见面回去。一些函数是恒久不会见回到的,

按部就班 abort或者 exit之类,调用它们就是象征结束程序. 所以
warning就展示没必要.

 

43) _Static_assert

解释:

  编译器期间断言, 当 #if #error 作了(预编译)之后, 编译器断言.
assert是运行时断言.用的早晚看现实的需求.
演示:

_Static_assert(__STDC_VERSION__ >= 201112L, "C11 support required");
// Guess I don't really need _Static_assert to tell me this :-(

 

44) _Thread_local

解释:

  到这边快扯完了, 其实C11业内是单深好的尝试. 为C引入了线程和原子操作.
各种安全特点补充. 可以说C强大了.

而还远不够, 因为越来越丑了. C11吗C引入了线程 在
头文件<threads.h>中定义.但为允许编译可以不实现.

_Thread_local是新的仓储类修饰符, 限定矣变量不克当差不多线程之间共享。
演示:

_Thread_local static int i;
// Thread local isn't local!

语义上虽是线程的私房变量.

   

晚记 – 我们吧未青春了

  如果来问题欢迎补充, 关键字当字典用呢是好之 哈哈啊

  审男子汉 
http://music.163.com/\#/m/song?id=31421394&userid=16529894**
**

  科学 1

  你晤面内心痛啊, 已经方寸痛了 /(ㄒoㄒ)/~~