C核心 那些只第一字。C核心 那些个重大字。

概述 – C语言老矣

概述 – C语言老了

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

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

-> C89关键字

-> C89关键字

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
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

-> C99新增加关键字

-> C99新加关键字

_Bool _Complex _Imaginary inline restrict
_Bool _Complex _Imaginary inline restrict

-> C11初增加关键字

-> C11初长关键字

_Alignas _Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local
_Alignas _Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local

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

 下面容我细细分析从实际用法.(存在平台差异, 有问题特别欢迎评论上,
这虽一定给一个着重字字典)

 

 

C89 32个关键**

C89 32个关键**

1) char

1) char

解释:

解释:

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

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

当工程项目开发中推介用 

以工程项目开发被推荐用 

#include <stdint.h>

int8_t   -> signed char 
uint8_t  -> unsigned char
#include <stdint.h>

int8_t   -> signed char 
uint8_t  -> unsigned char

闲谈一点, 程序开发最常遇到的就是由说问题. 鸡生蛋, 蛋生鸡. 后面又分析
signed 和 unsigned

聊天一点, 程序开发最常遇到的就是是从说问题. 鸡生蛋, 蛋生鸡. 后面更分析
signed 和 unsigned

演示:

演示:

#include <stdio.h>

char c;
c = getchar();
rewind(stdin);
printf("c = %d, c = %c.\n", c);
#include <stdio.h>

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

 

 

2) short

2) short

解释:

解释:

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

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

推荐下 int16_t or uint16_t 类型.

引进使用 int16_t or uint16_t 类型.

演示:

演示:

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

 

 

3) int

3) int

解释:

解释:

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

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

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

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

演示:

演示:

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

 

 

4) unsigned

4) unsigned

解释:

解释:

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

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

理所当然当您用这个修饰变量的时候. 再利用 – 和 — 运算的时候肯定要小心

本来当你用者修饰变量的时候. 再下 – 和 — 运算的时光一定要是小心

演示:

演示:

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

 

 

5) long

5) long

解释:

解释:

  声明变量的上用!长整型 x86直达四字节, x64达到8许节.
一定非较int字节数少.  C99后出现long long类型8字节.

  声明变量的当儿用!长整型 x86及四字节, x64及8配节.
一定非较int字节数少.  C99从此出现long long类型8许节.

演示:

演示:

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

 

 

6) float

6) float

解释:

解释:

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

  声明变量的上用! 四许节. 精度是6-7位左右.  详细精度可以看 float与double的克及精度

演示:

演示:

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

 

 

7) double

7) double

解释:

解释:

  声明变量的早晚用!八字节,精度在15-16员左右.片时候压缩内存用float代替.

  声明变量的下用!八字节,精度在15-16各左右.有的时候压缩内存用float代替.

演示:

演示:

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

 

 

8) struct

8) struct

解释:

解释:

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

  定义结构体, 这个重大字用法广泛, 是大头. c
的关键思路就是面向过程编程. 撑起面向过程的洋就是结构体.

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

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

演示:

演示:

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

struct node node = { 1, NULL };

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

struct node node = { 1, NULL };

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

 

 

9) union

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 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用法, 利用内存对齐. 

重来平等种植 union用法, 利用内存对齐. 

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

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

再有很久以前利用union 实现内存字节对联合, 太多矣. 每个重要字用法,
确实很多, 很意外.

 

 

10) void

10) void

解释:

解释:

  这个是拖欠关键字. 用法特别多. 也是自家最为爱的重要性字. 用在函数声明中,
类型定义中.

  这个是拖欠关键字. 用法特别多. 也是我不过欢喜的要紧字. 用在函数声明中,
类型定义中.

演示:

演示:

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

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

// 万能类型定义, 指针随便转
void * arg = NULL;
// 函数声明
extern void foo();

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

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

 

 

11) enum

11) enum

解释:

解释:

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

  枚举类型, 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;
//
// 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各项单位从上向下递增.

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

 

 

12) signed

12) signed

解释:

解释:

  变量声明类型修饰符. 有符号型, 对比 unsigned 无符号型.
变量声明默认基本还是 signed, 所以多数别人就简单了.

  变量声明类型修饰符. 有符号型, 对比 unsigned 无符号型.
变量声明默认基本还是 signed, 所以多数别人就简单了.

演示:

演示:

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

自了, 平时无需着意加. 会让人口深恶痛绝麻烦. O(∩_∩)O哈哈~

当然了, 平时无需着意加. 会给人头痛麻烦. O(∩_∩)O哈哈~

 

 

13) const

13) const

解释:

解释:

  const修饰的变量表示是只不足修改的量. 和常量有点区别. 可以大概认为
const type val 是单单念之.

  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 都不能动
// 声明不可修改的量
const int age = 24;

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

实质上当c中挑大梁无呀改观不了的. 全是内存来回折腾, 软件大硬件~~

实在在c中挑大梁没有啊变动不了底. 全是内存来回折腾, 软件大硬件~~

 

 

14) volatile

14) volatile

解释:

解释:

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

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

常用在多线程代码中.

常用于差不多线程代码中.

演示:

演示:

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

然后使用loop的时刻, 其它线程修改, 当前线程也能对获取她的值.

之后采取loop的时, 其它线程修改, 当前线程也会是获取她的值.

 

 

15) typedef

15) typedef

解释:

解释:

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

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

演示:

演示:

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

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

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

 

 

16) auto

16) auto

解释:

解释:

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

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

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

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

演示:

演示:

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

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

无须为此生命周期结束之变量, 存在各种意外. 

 

 

17) register

17) register

解释:

解释:

  变量修饰符,只能修饰整形变量.表示期望此变量存放于CPU的寄存器上.现代编译器在拉开优化时候,

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

能够肯定程度及默认启用register寄存器变量.

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

演示:

演示:

#include <limits.h>

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

   ++i;
}
#include <limits.h>

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

   ++i;
}

是因为CPU寄存器是少的, 有时候你尽管声明的寄存器变量也恐怕只是一般变量.
printf(“&i = %p\n”, &i) 这种用法是非法.

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

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

寄存器变量不能够获取地址.

 

 

18) static

18) static

解释:

解释:

  static 用法特别广泛. 修饰变量, 表示变量是于静态区, 基本就是是全局区.
生存周期同系在周期.

  static 用法特别广泛. 修饰变量, 表示变量是于静态区, 基本就是是全局区.
生存周期同系在周期.

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

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

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]) { ... }
// 修饰全局变量, 只对当前文件可见
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

19) extern

解释:

解释:

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

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

演示:

演示:

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

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

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

当有时候候extern不写, 对于变量不行会起重定义. 对于函数是可以少省写法.
再拉一点

当然有时候候extern不写, 对于变量不行会出现重定义. 对于函数是足以少省写法.
再扯淡一点

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

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

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

 

 

20) break

20) break

解释:

解释:

  结束语句. 主要用来循环的跳转, 只能跨反到当下层级. 也用于switch
语句被, 跳出switch嵌套.

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

演示:

演示:

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


// break 跳出while循环
int i = 0;
while(i < 6) {
   if(i == 3)
      break;
} 
for(;;) {
   // 符合条件跳转
   if(six == 6)    
       break;
}


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

break用法主要和循环一块下, 还有do while. 但只能跨转当前层循环. 

break用法主要和循环一片下, 还有do while. 但不得不跨转当前层循环. 

 

 

21) case

21) case

解释:

解释:

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

  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 普通用法 和 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嵌套.

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

 

 

22) continue

22) continue

解释:

解释:

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

  跳了此次循环. 直接进行标准判断操作. for 和 while 有若干局别. for
会执行第三单后面的语句.

演示:

演示:

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

     // 上面continue 调到 ++i -> i < 20 代码块
}
// for 循环 continue
for(int i = 0; i < 20; ++i) {
    if(i % 2 == 0)
         continue;

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

 

 

23) default

23) default

解释:

解释:

  switch 分支的默认分支, 假如case都尚未进入那就算进入default分支.
default 可以省略break. c 语法中但是行.

  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;
}
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

24) do

解释:

解释:

  do 循环. 先实施循环体, 后再度实施基准判断.

  do 循环. 先实施循环体, 后重新实行规则判断.

演示:

演示:

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

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

} while(++i < 10);
register i = 0;
do {
    if(i % 2 == 0) 
           continue;

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

} while(++i < 10);

do while 循环有时候可以减掉一次于法判断. 性能更好, 代码更长.

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

 

 

25) else

25) else

解释:

解释:

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

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

演示:

演示:

#include <stdbool.h>

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



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

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

#else

#error "NOT __GNUC__, NEED GCC!";

#enfif
#include <stdbool.h>

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



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

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

#else

#error "NOT __GNUC__, NEED GCC!";

#enfif

 

 

26) for

26) for

解释:

解释:

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

  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(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) { } 写法好, 有同样种植不动条件判断的用意,
虽然汇编代码是一致的.

for(;;) {  } 比 while(true) { } 写法好, 有雷同栽不挪条件判断的意向,
虽然汇编代码是相同的.

 

 

27) goto

27) goto

解释:

解释:

  goto 是我第二爱好的关键字.  可以在脚下函数内逾转. goto
可以代替有循环.

  goto 是自身第二喜的基本点字.  可以在现阶段函数内逾转. goto
可以代替有循环.

演示:

演示:

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

再有就是是在工程支出被, goto 常用于复制的工作逻辑.

再有就是是以工程支出被, 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;
    }
    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

28) if

解释:

解释:

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

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

演示:

演示:

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

 

 

29) return

29) return

解释:

解释:

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

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

演示:

演示:

#include <stdlib.h>

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

   return EXIT_SUCCESS;
}
#include <stdlib.h>

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

   return EXIT_SUCCESS;
}

 

 

30) switch

30) switch

解释: 

解释: 

  条件分支语句. 很复杂的if else if 时候可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);
#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

31) while

解释:

解释:

  循环语词, 有do while 和 while 语句简单栽.

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

演示:

演示:

#define _INT_CNT (10)

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

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

 

 

32) sizeof

32) sizeof

解释:

解释:

  这个重大字为号称 sizeof 运算符. 计算变量或项目的字节大小.
这个要字特别好用!

  这个关键字呢号称 sizeof 运算符. 计算变量或项目的字节大小.
这个重要字特别好用!

演示:

演示:

sizeof (main)   -> x86 上四字节

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

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

及此C89保留的重大字基本解释了毕.

顶这边C89保留的要字基本解释了毕.

 

 

C99 5个新增加关键**

C99 5只新长关键**

33) _Bool

33) _Bool

解释:

解释:

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

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

演示:

演示:

#include <stdbool.h>

bool flag = true;

// 或者直接用
_Bool flag = !0;
#include <stdbool.h>

bool flag = true;

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

 

 

34) _Complex

34) _Complex

解释:

解释:

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

  对于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;
}
#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标准兑现

骨子里以复数类型中, gcc标准兑现

#define complex         _Complex
#define complex         _Complex

倘于VS 中落实具体为

一旦当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;
#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.
当然除了科学计算会为此到复数, 其它很少.

毕竟的而言, 学习C 最好之平台即是 *nix 平台上用 Best new GCC.
当然除了科学计算会因此到复数, 其它很少.

此处VS 和 GCC实现无一样. 用起来需要注意.

这边VS 和 GCC实现非一样. 用起来用注意.

 

 

35) _Imaginary

35) _Imaginary

解释:

解释:

  虚数类型. _Complex 复数类型的虚部. 例如 10.0i, 10.8if 等等. 
这个要字于VS 上并未落实. 其实自己耶道没必要.

  虚数类型. _Complex 复数类型的虚部. 例如 10.0i, 10.8if 等等. 
这个主要字于VS 上从不落实. 其实我啊道没必要.

和_Complex有重叠.

和_Complex有重叠.

演示:

演示:

  这个重点字无法以代码中表示. 系统保留, 我们无克使用.

  这个关键字无法在代码中表示. 系统保留, 我们无可知使用.

 

 

36) inline

36) inline

解释:

解释:

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

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

取而代之宏. 宏能不用就无用. 函数声明的当儿绝不加inline 需要加extern,
定义之时光需要加inline.

取而代之宏. 宏能不用便不用. 函数声明的时段不要加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);
}
/*
 * 对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

37) restrict

解释:

解释:

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

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

享有修改该指针所负于内容之操作全部都是基于(base
on)该指针的,即未存其他进行修改操作的路;

怀有修改该指针所指为内容的操作全部都是基于(base
on)该指针的,即无存在任何进行改动操作的路径;

如此的结果是扶助编译器进行更好之代码优化,生成更有效率的汇编代码。

这样的产物是支援编译器进行双重好的代码优化,生成更有效率的汇编代码。

演示:

演示:

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

地方是挑自GCC 的 string.h中. 其实正式用法

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

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

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

Pelles C 编译器可以完全支持 restrict.

 

 

C11 7个新添关键字

C11 7只新长关键字

38) _Alignas

38) _Alignas

解释:

解释:

  内存对合之操作符. 需要以及_Alignof配合以,
指定结构的对准齐方式.
演示:

  内存对一起之操作符. 需要以及_Alignof相当使用,
指定结构的对准齐方式.
演示:

#ifndef __cplusplus

#define alignas _Alignas
#define alignof _Alignof

#define __alignas_is_defined 1
#define __alignof_is_defined 1

#endif
#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;
}
#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 对齐方式对同步返回回去.

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

 

 

39) _Alignof

39) _Alignof

解释:

解释:

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

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

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

 

 

40) _Atomic

40) _Atomic

解释:

解释:

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

  原子操作, 原子锁. 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;
}
#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

41) _Generic

解释:

解释:

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

  这个于叼, 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;
}
#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

42) _Noreturn

解释:

解释:

  修饰函数,绝对免会见生出返回值. _Noreturn 声明的函数不见面回去回.
引入这新的函数修饰符有星星点点独目的:

  修饰函数,绝对不见面时有发生返值. _Noreturn 声明的函数不会见回到回.
引入这新的函数修饰符有有限只目的:

  • 清除编译器对没 return的函数的警告. 
  • 许某种只对不回来函数的优化.
  • 消编译器对尚未 return的函数的警告. 
  • 许某种只对非回来函数的优化.

演示:

演示:

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

更拉一点, GCC中等同于 __attribute__((__noreturn__)),
在VC中一般功能是 __declspec(noreturn).

重新拉一点, GCC中等同于 __attribute__((__noreturn__)),
在VC中貌似功能是 __declspec(noreturn).

她不是说函数没有回去值,而是说如你调了之函数,它世代不会见回来。一些函数是永恒不会见回去的,

她不是说函数没有回来值,而是说而你调了此函数,它世代不见面回到。一些函数是永远不会见回来的,

论 abort或者 exit之类,调用它们就是代表结束程序. 所以
warning就亮没必要.

遵 abort或者 exit之类,调用它们就是代表结束程序. 所以
warning就显没有必要.

 

 

43) _Static_assert

43) _Static_assert

解释:

解释:

  编译器期间断言, 当 #if #error 将完(预编译)之后, 编译器断言.
assert是运行时断言.用的下看具体的需求.
演示:

  编译器期间断言, 当 #if #error 将完(预编译)之后, 编译器断言.
assert是运行时断言.用的当儿看具体的需求.
演示:

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

 

 

44) _Thread_local

44) _Thread_local

解释:

解释:

  到此地快扯完了, 其实C11标准是个要命好的尝试. 为C引入了线程和原子操作.
各种安全特点补充. 可以说C强大了.

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

唯独还远远不够, 因为尤其丑了. C11也C引入了线程 在
头文件<threads.h>中定义.但也同意编译可以不实现.

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

_Thread_local是新的囤类修饰符, 限定了变量不可知在差不多线程之间共享。
演示:

_Thread_local是初的蕴藏类修饰符, 限定了变量不克于差不多线程之间共享。
演示:

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

语义上就是是线程的个人变量.

语义上即是线程的个体变量.

   

   

继记 – 我们为未青春了

晚记 – 我们呢非青春了

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

  如果发题目欢迎补充, 关键字当字典用也是好的 哈哈啊

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

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

  图片 1

  图片 2

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

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

 

 

相关文章