知识性
变量储存类型
动态储存类别
auto:自动变量 编译器默认变量
register:寄存器变量 变量值存放在cpu的寄存器中,存取速度快,个数有限,只有局部自动变量和函数形参才能定义,不能进行取地址操作
静态储存类别
extern:外部变量,即全局变量在定义在函数外部 ,当引入变量其他文件或定义在使用后时需要声明
static:静态变量,在定义时初始化初始化只执行一次,未初始化时会自动赋值为0
内部函数与外部函数
内部函数:只能被本源程序文件的函数调用,限定了函数的作用域,便于不同用户方便编写不同函数,不必考虑重名问题。
格式如下:
static 数据类型 函数名(形参列表) { 说明部分; 语句部分: }
外部函数:c语言默认函数类型,可以被其他源程序文件中的函数调用
格式如下:
[extern] 数据类型 函数名(形参列表) { 说明部分; 语句部分: }
运算符优先级
!>算数运算符>关系运算符>&&>||>赋值运算符
顺序点
特点
该点前的表达式的所有副作用在程序执行到达该点前发生完毕(副作用:在求值中对变量不但引用而且修改)
原则1:在两个顺序点之间一个变量保存的值只能修改一次
原则2:在两个顺序点之间必须是引用与修改顺序确定的情况下
预处理
编译预处理:以#开头的特殊语句
预处理功能:宏定义,文件包含,条件编译
细节点
1函数返回值不能是局部变量的地址,函数调用结束后局部变量会销毁
2复合语句:将两条以上的语句用{}括起的语句
3atexit():当main函数终止后跳转atexit,同时atexit函数按后进先出的方式注册这些函数因此最后注册的函数先调用
4typeef 不能递归定义
题目类型
1字符串长度 char a[]="abcdef" char b[]={'a','b','c','d','e','f'} 答案:数组a比数组b长 2宏定义的整体替代 #define add(x) x+x int m=1,n=2,k=3,sum sum=add(m+n)*k /*sum=m+n+m+n*k */ 3strlen与sizeof的计算 char c[]="he\\\t\0will" r=strlen(c) /* h e \\ \t r=4*/(在二进制文件中\会变成单个字符) sizeof:在编译的时候开始执行 sizeof(++i)=sizeof(i)因此sizeof只能求静态分配空间的大小 4全局变量与局部变量 当局部变量与全局变量重名时,局部变量会屏蔽全局变量独立 5自增(自减)的副作用与贪心算法 自增(自减)不能用于常量和表达式 ++a:a=a+1,即a自增1 a++:a先创建一个副本.然后a自增1,最后返回副本值。 结论:a++不能作为左值(因为作为左值,改变的是副本的值) ,并可知++a的效率比a++高 i+++++i :c解析表达式时会采用贪心算法,即原式 (i++)++ +i. 贪心算法:在移动到下一个符号前在单个符号中包含尽可能多的字符 例子:y=x/*p会把p当成注释符,正确表达应该是y=x/(*p)*/ 6运算符 int i=0,a=1,b=2,c=3 i=++a||++b||++c i=1 a=2 b=2 c=3(当++a为真时,表达式即返回) 7精度问题 float类型与0值比较的if语句(x<0.000001&&x>-0.000001)float的精度为6 float a,b,c a+b+c==b+a+c 不一定为真 除非两数的差在float精度之内、 8赋值问题与循环计算 for(int i=0;i=0;i++); 循环执行次数 : i=0为赋值,因此循环0次,同理如果i=1,则是无限循环 unsigned short i,j for(i=0,j=2;i!=j;i+=5,j+=7) 2+7n-5n=65536 即j刚好比i多执行一圈 unsigned short的取值为0~65536 9指针与数组 *((void **)&f),(void**) void*可以看成先将f转换为无类型地址,*可以看成根据&f的基类型将无类型地址转换为基类型地址 最外面的*是取值 所以原式==*&f即f 当字符数组部分初始化时,其余元素将自动赋空格符(ASCLL码为32) 数组名作为函数参数时会变成指针 sizeof(a)==4 10错误分析 int i, * p, ** p = &p; p = (int*)malloc(3 * sizeof(int)); for (i = 0; i < 3; i++) *(p + i) = i + 1; printf("%d\n", **(++p)); free(p); 二级指针++p指向p的下一个地址,该地址不是有效数据的地址,**pp出现取垃圾地址内容