1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 回首C语言关键字(~回首向来萧瑟处~)

回首C语言关键字(~回首向来萧瑟处~)

时间:2023-02-28 08:42:17

相关推荐

回首C语言关键字(~回首向来萧瑟处~)

开篇废话:

本文意在回顾 C 语言中的关键字,整理文件发现当时做的这些笔记还是蛮用心的,有临摹

前辈的足迹也有自己的理解和体会。时至今日已经跨过一半,对不起过去半年,今天

拿这篇关键字开篇,开启自己的程序猿心路,主要记录一下自己遇到的问题和学习的经历,

方便自己。如果能对别也有用那就更开心了,由于自己还很菜,理解和体会都很有限,如

果你打开发现了错误还请不吝赐教,随便评论,不要客气,我都会很感激的。首篇废话就

这么多吧,我可能废话比较多,哈哈,批评我吧~

C关键字

/*** 到目前C语言中有32+5+7=44个关键字,具体如下:* * ->C89关键字* * char short int unsigned* long float doublestruct * unionvoid enum signed* constvolatile typedefauto* register staticexternbreak * case continue defaultdo* else for goto if* returnswitchwhile sizeof* * ->C99新增关键字* * _Bool_Complex[复杂的] _Imaginary[虚构的] inline restrict[限定/约束]* ** ->C11新增关键字* * _Alignas Alignof _Atomic _Generic * _Noreturn_Static_assert _Thread_local***/

C8932个关键字解释

/* 1) char解释: 声明变量的时候用,char 占1个字节8bit,多数系统上是有符号的(arm 上无符号)范围 [-128, 127]在工程项目中开发推荐用int8_t -> singned charuint8_t -> unsigned char*/char c = 'p';/*2) short解释:声明变量的时候用,short占2个字节,为无符号的,默认自带signed范围[-2^15, 2^15-1]2^15 = 32800推荐使用 int16_t or uint16_t 类型*/short port = 8080; /*3) int解释:声明变量的时候用,int声明的变量占4个字节,有符号,范围[-2^31,2^31-1]2^31推荐使用:int32_t or uint32_t 类型开发,方便移植*/int i = 0;/*4) unsigned 解释:变量类型修饰符,被修饰的变量就是无符号的,范围>=0,unsigned 只能修饰整型的变量当然你用这个修饰变量的时候,再使用++和--运算的时候一定要小心。*/unsigned int i = 0; //正确unsigned short s = 0; //正确unsigned float f = 0.11f; //错误/*5) long解释:声明变量的时候使用,长整型x86上4个字节,x64上8个字节,一定不比int字节数少c99之后出现long long 类型为8个字节*/long l = 4;long long ll = 8;/*6) float解释:声明变量的时候用,4个字节,精度是6-7位,详细精度可以看:/dxy612/article/details/5518477*/float f = -0.12f; /*7) double解释:声明变量的时候用,8个字节,精度在15-16位左右,有的时候压缩内存用float代替*/double d = 2e13;/*8) struct解释:定义结构体,这个关键字用法很广,是大头。C的重要的思路就是面向过程编程,撑起面向过程的大头就是结构体。*/// 普通结构体struct node {int id;struct node *next;};struct node n = {1,NULL};// 匿名结构体struct {int id;char* name;} per = {2,"Tom"}; /*9) union解释:定义共用体,用法很花哨,常在特殊库函数封装中用到,技巧很强*/// 普通定义union type {char c;int i;float f;};union type t = {.f = 3.33f};// 匿名定义union {...} t = {...};//类型匿名定义struct cjson {struct cjson *next; //采用链表结构处理,放弃二叉树结构,优化内存unsigned char type; // 数据类型和方式定义,一个美好的愿望char *key;// json内容那块的key名称union {char *vs; // type == _CJSON_STRING, 是一个字符串double vd;// type == _CJSON_NUMBER, 是一个num值((int)c->vd)转成int或bool}; }; /*什么是大小端?Endian表示数据在存储器中的存放顺序,大端(Big Endian): 是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似把数据当做字符串顺序处理:地址由小向大增加,儿数据从高位往低位。小端(Little Endian): 是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效的结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。这两种模式,泥瓦匠记忆宫殿:“小端低低”。这样就知道小端的模式,反之大端的模式。/Alandre/p/4878841.html*/// 在来一种union用法,判断大小端,笔试题中长见inline boolsh_isbig(void) {static union {unsigned short s;unsigned char c;}U = {1}; // 1 -> 0x0001;return U.c == 0;}/*10) void解释:这个关键字用法很多,也是用在函数声明中,或函数参数*/// 函数声明extern void foo();// 函数参数约束extern void foo(void); //函数参数为void表示函数是无参数的,否则是任意的// 万能类型定义,指针随便转void* vp = NULL;/*11) enum解释:枚举类型,C中枚举类型很简陋,相当于一种变相的INT宏常量,估计也许是INT宏常量和枚举并存的原因问题1有些面试题中会问你enum 和#define 的区别:1. #define 宏常量是在预编译阶段进行简单的替换;enum常量则是在编译的时候确定其值2. 一般在调试器里,可以调试枚举常量,但不是不能调试宏常量。3. 枚举可以一次定义大量相关的常量,而#define 宏一次只能定义一个。问题21. 枚举能做的事,#define 宏能不能做到?如果能,那为什么还需要枚举?答:能,枚举可以自增1,这样不用每一个值都定义,而宏必须每个值都定义,而枚举是一个集合,代表一类值,像代码中的颜色归为一类方便使用,而#define不能形成集合2. sizeof(ColorVal)的值是多少?为什么?enum Color{GREEN = 1,RED,BLUE,GREEN_RED = 10,GREEN_BLUE}ColorVal;答:值为4,ColorVal一个枚举变量,而枚举变量代表一个整数。*///// flag_e -全局操作基本行为返回的枚举,用于判断返回值状态的状态码// >=0 标识Success状态,< 0 标识Error状态// // 枚举变量完全可以等同于int变量使用,枚举值等同于宏INT常量使用,枚举的默认值// 是以1为单位从上向下递增。//typedef enum {Success_Exit =2, //希望存在,设置之前已经存在了Success_Close =1, //文件描述符读取关闭,读取完毕也返回这个Success_Base =0, // 结果正确的返回宏Error_Base=-1, //错误类型,所有错误都用它,在不清楚的情况下Error_Parm=-2, //调用参数错误Error_Alloc=-3, //内存分配错误Error_Fd =-4, //文件打开失败} flag_e;/*12) signed解释:变量声明类型修饰符,有符号型,对比unsigned无符号型,变量声明默认基本都是singned ,所有多数别就省略了*/signed int piyo = 0x12345678;/*13) const解释:const 修饰的变量表示是一个不可修改的量,和常量有点区别,*/// 声明不可修改的量const int age = 24;// 修饰指针const int *pa = NULL; //pa指向的值(*pa)是不能修改int *const pt = NULL; //pt不能指向新的指针,pt指向的值(*pt)可以修改const int *const pc = NULL; //pc和pc指向的值(*pc)都不能修改 /*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 treetypedef struct tree * tree_t;// 重定义变量类型typedef unsigned long int ub4; /* unsigned 4-byte quantities*/typedef unsignedchar ub1; /* unsigned 1-byte quantities*/// 定义一个函数指针typedef uint32_t (*crc_func)(uint32_t crc, const void *buf, size_t len);// 使用crc_func crc32c; //声明一个crc_func类型的变量,实际就是一个函数指针,指向函数的首地址/*16) auto解释:变量类型声明符,auto变量存放在动态存储区,随和声明周期{开始},结束而立即释放,存在在栈上默认变量都是auto的,基本是不写*///演示{// 生存期开始int a = 0;auto int p = 1;// 生存期结束}/*17) register解释:修饰变量,这个关键字请求编译器尽可能的将变量存放在CPU内部寄存器中而不是通过内存寻址访问以提高效率,注意是尽可能,不是绝对。实用register修饰的注意点虽然寄存器的速度非常快 ,但是实用register修饰符也要些限制的,register变量必须是能被cpu寄存器所能接受的类型意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度,而且register变量可能不存在在内存中,所以不能用取地址运算符"&"来获取register变量的地址。*/ #include <limits.h>register int i = 0;while (i < INT_MAX) {++i;}/*18) static 解释: static用法很广,修饰变量,函数,从字面上看static 很安静,这个关键字在C++中做了扩展,在C语言中重要就前面提到的两个作用。1. 修饰变量变量又分为局部变量和全局变量,但它们都在内存的静态区。静态全局变量,作用域仅限于变量被定义的文件中,其他文件即使用extern声明也没有办法使用准确的说:作用域是从定义之处开始,到文件结尾处结束,静态局部变量:在函数体里面定义的,就只能在这个函数里用了,同一个文档中的其他函数也用不了,由于被static修饰的变量总是存在内存的静态区,所有即使这个函数运行结束,这个静态变量的值也不会被销毁,函数下次使用时任然能用这个值。看下面一段代码:static int j;void fun1(void) {static int i = 0;i++;}void fun2(void) {j = 0;j++;}int main(){int k = 0;for(k = 0; k < 10; k++) {fun1();fun2();}return 0;}此时i和j的值分别是多少?我们来分析一下哈:首先毫无疑问,j 是个全局静态变量,调用一次fun2()后,它的值始终没有变,所有调用10次值还是1i这个变量是一个局部静态变量,值存放在内存的静态区,调用一次fun1()结束后它的值不会被销毁,函数下次调用的时候任然使用这个值,所有调用10次它的值一次为,1,2,3,4,5,6,7,8,9,10,112. 修饰函数函数前面加static使得函数成为静态函数,但此处"static"的含义不是指存储方式,而是指对函数作用域仅局限于本文件(所有称内部函数)使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数是否会与其他文件中的函数同名。// C99之后加的static新用法,编译器优化/ static 只能修饰函数第一维,表示数组最小长度,方便编译器一下取出所有内存进行优化*/int sum(int a[static 10]) { ... } /*19) extern 解释:extern (外面的,外来的)可以置于变量或函数前,以表明变量或函数的定义在别的文件中下面代码用到的这些变量或函数是外来的,不是本文件中定义的,提示连接器遇到此变量和函数时在其他模块中解析/绑定此标识符。*/// 声明引用全局变量extern int G_arg;// 声明引用全局函数,(主动声明,希望外部可以调用)extern int kill(int sig, int val);// 当然有时候extern不写,对于变量不写会出现重定义,对于函数时可以缺省的/*20) break解释:结束语句,主要用于循环的跳出,只能跳出到当前层级,也用于switch语句中跳出swithc嵌套*/// 演示 for循环for(;;) {// 符合条件跳转if(n == 10)break; // 跳出for循环}/*21) 22) 23) switch & case & default 解释:21)switch :条件分支语句,很复杂的if else if时候可以用switch22)case : 语句中分支语句,确定走哪个分支23)default: switch 分支的默认分支,所有case都没有进入就到default分支*/// 演示switch (errcode) {case SSL_ERROR_ZERO_RETURN:/* Possibly a clean shutdown. */if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN)event = BEV_EVENT_EOF;elsedirty_shutdown = 1;break;case SSL_ERROR_SYSCALL:/* IO error; possibly a dirty shutdown. */if ((ret == 0 || ret == -1) && ERR_peek_error() == 0)dirty_shutdown = 1;break;case SSL_ERROR_SSL:/* Protocol error. */break;case SSL_ERROR_WANT_X509_LOOKUP:/* XXXX handle this. */break;case SSL_ERROR_NONE:case SSL_ERROR_WANT_READ:case SSL_ERROR_WANT_WRITE:case SSL_ERROR_WANT_CONNECT:case SSL_ERROR_WANT_ACCEPT:default:/* should be impossible; treat as normal error. */event_warnx("BUG: Unexpected OpenSSL error code %d", errcode);break;}/*24) continue解释:跳过此次(本轮)循环,直接进行条件判断操作,进入下一轮循环,for和while循环有些区别,for会执行第三个后面的语句*/// 演示for(int i = 0; i < 20; ++i) {if(i % 2 == 0)continue; // 满足if跳到 ++i,再到条件 i<20}/*25) do ... 26) while 27) for解释:C 语言中的三种循环25) do: do循环,先执行循环体,在执行条件判断,先保证循环体执行一遍在判断条件在一个菜单的程序设计的时候用do...while 比较好,首先给出选择。26) while: 循环,先判断while后的条件,只有条件真才执行里面的代码块,常用的还有就是一种死循环的写法 while(1)27) for: 循环,for循环很容易的控制循环次数,多用于事先知道循环次数的情况下*/ // 演示/* do -while 循环 */do {event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);xcount++;} while (count != fired);/* while 循环 */while(1) {if('#' == GetInputChar()) break;}/* for 循环 */for (i = 0; i < 25; i++) {tv = run_once();if (tv == NULL)exit(1);fprintf(stdout, "%ld\n",tv->tv_sec * 1000000L + tv->tv_usec);} /*28) if ... 29) else解释:28) if: if分支语句,可以单独使用,可嵌套29) else: else分支,必须和if分支对应,和if分支条件相反*/ n = recv(fd, (char*)&ch, sizeof(ch), 0);if (n >= 0)count += n;elsefailures++;if (writes) {if (widx >= num_pipes)widx -= num_pipes;n = send(pipes[2 * widx + 1], "e", 1, 0);if (n != 1)failures++;writes--;fired++;}/*30) goto解释:关于goto这个关键字,褒贬很多,原因就在于它太自由,可以灵活的跳转,在结构化编程中它有了很多争议,如果不加以限制,它的自由跳转的确会破坏结构化设计的风格所有使用它一定要慎重,下面我们用一段真实代码展示它的魅力,*/// 演示if (evbuffer_expand_fast_(buf, to_alloc, 2) < 0) {goto done;}for (n = 0; n < n_vec; n++) {/* XXX each 'add' call here does a bunch of setup that's* obviated by evbuffer_expand_fast_, and some cleanup that we* would like to do only once. Instead we should just extract* the part of the code that's needed. */if (evbuffer_add(buf, vec[n].iov_base, vec[n].iov_len) < 0) {goto done;}res += vec[n].iov_len;}done:EVBUFFER_UNLOCK(buf);return res;/*31) return 解释: return 用来终止一个函数并返回其后面跟着的值使用return 不可返回指向“栈内存”的“指针”,因为该内存在函数体结束后就被自动释放了*/// 演示#include <stdio.h>int main(int arg, char* argv[]) {......return EXIT_SUCCESS;}/*32) sizeof 解释:也称为sizeof运算符,计算变量或类型的字节大小,它常被误认为是个函数面试中也经常有它出现,下面我们看看它的用法*/// 演示 x86上int *p = NULL;sizeof(p) 的值是多少---> 4sizeof(*p)呢?---> 4int a[100];sizeof(a)的值是多少 ---> 400sizeof(a[100])的值 ---> 4sizeof(&a)的值---> 4sizeof(&a[0])的值 ---> 4int b[100];void func(int b[100]) {sizeof(b); // sizeof(b)的值 ---> 4}// 常用一种写法获取数组长度#define LEN(arr) (sizeof(arr) / sizeof(*(arr)))#define LEN(arr) (sizeof(arr) / sizeof(arr[0]))

到此 C89 的32个关键字都就介绍完了,对于 C99 和 C11的关键字,后续完善.....

后记

《意颓废》

意颓废,人难寐。

夜夜长街空买醉。

路茫茫,断离肠。

梦牵魂索,独守西窗,伤!伤!伤 。

花儿碎,风流泪。

曲悲弦断连心肺。

恋成殇,心透凉。

一朝白头,只为情狂,怆!怆!怆。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。