C语言再学习
- 在C语言中,const关键字并不表示真正的常量,真正的含义是”read only”,故而下面的写法是有问题的:
Const int two=2;
Switch(i){
Case 1:
Case two :
}
2. 在switch语句中要注意到break的用法:break语句事实上跳出的是最近的循环语句或者switch语句.
3. Char *a[]={“aaaa”,
“bbbb”
“cccc”,};
结果数组a中只有两个元素! 因为语法处理上把 “bbbb”和 “cccc”自动合并了,就因为”bbbb”后面缺少了一个逗号.注意还有个问题,”cccc”后面却多了一个逗号,会不会有什么问题??
答案是没有问题!它的存在与否没有关系.但是值得注意的是在枚举声明等等操作时是不可以这样的!
4. Void a(char * string){
Static char sep=’ ’;
Printf(“ ”)……..
Sep=’,’;
}
这样就可以做到第一次输出时以空格作为间隔符但是之后均以逗号作为间隔符.
5. 在定义C语言函数时,缺省情况下函数的名字是全局可见(也可以用extern显示声明)的,也就是说这个函数对于链接到它所在的目标文件的任何东西是可见的,如果想限制,就得在函数前加上static(函数在此文件之外不可见).
6. C语言常见的符号重载:
符号 |
含义 |
static |
在函数内部,表示该变量的值在各个调用间保持延续性 |
在函数层面,表示该反函数只对所在目标文件可见(默认全局可见) |
|
extern |
用于函数定义,显示声明函数是全局可见的 |
声明变量,但没有定义该变量 |
|
void |
作为函数返回类型,表示不返回任何值 |
声明指针类型 |
|
参数列表中,表示无参数 |
|
* |
乘法运算符 |
用于指针,表示间接引用 |
|
在声明中表示指针 |
|
& |
位的与运算 |
取地址操作符 |
|
< |
小于运算符 |
#include <….> |
|
() |
函数定义中包围参数;调用函数;改变表达式运算次序;强制类型转换;定义带参数的宏;包围sizeof操作符的操作数 |
() |
函数定义中包围参数;调用函数;改变表达式运算次序;强制类型转换;定义带参数的宏;包围sizeof操作符的操作数 |
7. 符号重载存在的问题.例如,p=N * sizeof * q;这个语句怎么理解?
答案是这里面只有一个乘法,因为sizeof操作符把指针q指向的东西也就是*q当成操作数.
8. C语言常被误解的运算符优先级问题枚举:
表达式 |
实际含义 |
*p.f |
对p取f偏移,作为指针,然后进行解除应用操作:*(p.f) |
Int *a[] |
A是一个元素为int指针的数组 int *(a[]) |
Int *f() |
F为一个函数,返回类型为int* :int *(f()) |
C=gerchar() != EOF |
C=( gerchar() != EOF) |
I=1,2 |
(I=1),2 |
9. 运算符的结合性(类似于在a=b=c这种语句中,是先计算a=b还是b=c):
一般而言运算符是具有右结合性质的,如赋值符号,当然了也有是左结合的,比如位操作符。
特殊注意的是&&之类的逻辑运算符,是具有短路性的!!也就是说在类似于if(a&&b)的语句中如果判断出来a为假,那么就不会再去计算b的真假了,为什么???因为在a为假的情况下(a&&b)肯定是假了,这就是短路原则。
10. 一个问题:就算掌握了优先级和结合规则,还是有问题
a) X=f()+g()*h()
我们知道是会先计算g()*h(),然后加上f(),但是g(),h()两个函数谁先计算又是未知的,也就是说你不知道是g()先调用还是h()先调用。类似的,f()可能在乘法前或者后面执行!!!
b) 那为什么呢?
这样便于编译器方便选择,充分利用自身的特点,或者充分利用存储于寄存器的值。
11. 建议:只记住两个优先级就好了,乘除法由于加减法,在涉及其他的操作符时候一律加上括号!