阅前须知:此篇博客的大部分内容来自《C语言深度解剖》一书以及网上查阅各个资料还有自己的亲自实践。代码主要运行在linux环境下和VS2013环境下,希望读者看了以后不要照抄,要学会结合自己的思考,本篇博客主要记录了部分关键词拓展或者说是用到该关键词需要注意的地方,说白了就是死命抠细节,不是单纯介绍关键词,所以不一定适合入门的人看。还有!本篇博客内容仅仅局于C语言,有些东西可能放在C++上还有别的含义和作用,笔者不能一一成列实在抱歉。可以把他看做成笔者的学习总结,谢谢审阅,欢迎评价。
一.从static和extern开始。
static的作用比较广泛,主要分在两个方面:
1.修饰变量。
修饰变量也分修饰全局变量和修饰局部变量——前者作用呢是让该变量只能用于被定义的文件中,有点像怕老婆跑了的感觉,就算其他文件用extern声明也不能用,嘿嘿,就是这么酷。
后者则是为了延长变量的生命周期,本来局部变量的生命周期是所在函数一结束,就会被释放,现在不一样了,要等程序结束,他才会嗝屁。
至于为什么?因为局部变量本来是创建在栈里的,但因为加了static之后他就变了身份,他成了一个静态变量,需要把他放在static区域,也就是静态存储区域,这个时候他的命运不再由函数把控,而是把他的命运和应用绑在一起,应用结束的时候他才被释放。(一夜暴富的感觉)
2。修饰函数
修饰函数的作用和修饰全局变量的作用蛮像的,目的就是为了不让别的文件用自己的函数。
——static在平时写代码的时候也比较常用,所以我也不用举例子啥的。如果你说你看不懂上面的extern,没事我们等会就讲了;如果你说你看不懂“生命周期”,没事,以后代码写多了,你和代码就有感情了,代码就是你的第二个老婆啊~老婆怎么会是死气沉沉的;如果你说你看不懂栈(stack)啊,静态区(static)啊,如果你下定决心要学好C语言,这个方面还是要好好学的,了解一个变量存在在内存的位置,了解他的调用过程,还有排列的方式,可以看看我前面那篇博客,当然我觉得网上还有更好的,大家一起努力!
extern的作用主要就是声明外来变量或函数。
务必记住,extern是声明,不是定义,看下面代码:
A文件: B文件: int i=10; extern i; static int tmp=20; extern fun(); int fun () { return tmp; }
当然你也可以试试给B文件加一个“extern tmp”,然后再在B文件里找个什么代码用一下tmp,看看可不可行。我上面虽然讲了,但还是希望你实践一下,万一你那个编译器可以通过呢(开个玩笑,怎么可能)。
这里可以引申几个问题,你都可以回去试一下,我都在这里解答了:
1.extern后面可以跟类型吗?跟了类型会让变量类型强转吗?
答:可以(除了“void”),准确说是必须跟原来的类型,会的。如果改成“extern float i”,i的值就变0了,至于为什么变0,这是因为 浮点数 和 整型以及字符型 数据在内存中的存储方式不同。如果你现在不懂,将来一定要懂!很重要!
2.extern后面的变量在声明时可以给他赋值吗?
答:不可以。其实某种意义上来讲是可以的,因为你是程序员你想怎么输就怎么输,但是编译器会报错,这就又回到了我们上面在“生命周期”提到的代码情感问题了,你想做一件事,但是你老婆不愿意,那你能做吗?当然不行!活腻了这不是。
3.extern声明完变量后再赋值可以吗?
答:可以,必须放在函数里赋值。但是有什么意义呢,干嘛不自己定义一个,而要去用别人的?没必要啊。
二.关于各类基本数据类型。
我们知道常见的基本数据类型无非:short,int,long,char,float,double,long long。
你开始学这一方面的知识的时候,一定要了解这些类型的数据的长度,你问我怎么知道?可以上网查,也可以写个代码用 sizeof(数据类型) , printf 一下,你就知道答案了,sizeof我们一会也会讲,这是个大考点。
看下面代码:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<Windows.h> int main() { char a[1000]; int i; for (i = 0; i<1000; i++) { a[i] = -1 - i; } printf("%d ", strlen(a)); system("pause"); return 0; }
最后答案是255,为什么不是1000呢?很奇怪吧,其实也不奇怪,记住char只有8位——也就是一个字节,存到256的时候读的时候是个0,strlen有比较笨,它只知道读到0就停下来,所以值为255。
还有关于float,double浮点型数和0的比较,千万千万不要去直接和0比,一定要和0的近似值比!!!
#define PRE 0.00000001 //宏定义一个精度 ... float i =0.1; ... //----------错误↓-------------- if(i=0.0) { ;//code } //----------正确↓--------------- if(i<=PRE&&i>=-PRE) { ;//code } ...
多的也都不写了,这些关键词要注意的就是存储方式还有占空间大小的问题。再多说一点:
养成命名的好习惯,比如一些define宏定义的东西,一些只读变量,一些枚举类型的变量,最好用大写。这个不能教,每个人有个人的习惯,这个时候英语好变得有优势了(欲哭无泪),要注意简洁,也要易懂。推荐一本书《高质量C C++编程》,有讲一些关于命名的东西。
三.sizeof,顺便一提strlen。
记住,sizeof是一个关键字,不是函数。
怎么证明?
int i=10; A)sizeof(int); B)sizeof(i); C)sizeof int; D)sizeof i;
将上面的代码一一放到编译器里尝试,证明都是可以通过的,如果你有了解到C语言的操作符,你会知道操作符里有一个叫做“函数调用”的操作符,说白了就是“()”,所以可以证明,sizeof是关键字不是函数。
需要注明的是,sizeof(字符串)的时候,会把字符串的‘