C陷阱和缺陷
1. a+++++b 的含义是什么?
#include <stdio.h> int main(int argc,char** argv) { int a = 1; int b = 2; int c = 0; c = a++ + ++b; printf("C's value is%d\n",c); return 0; } #如果 c=a++a+++b; 会报lvalue required as increment operand
2.模拟计算机启动硬件将调用首地址为0位置的子例程
(*(void(*)())0)()
理解上面的代码:
1.括号优先级最高
2.假设fp变量是一个函数指针,如果调用fp所指向的函数 ->(*fp)() ANSIC C 标准允许简写成fp() 但是我们得记住这是一个简写 因为编译器会自动判断需要的是一个指针,如果不是会报错。(对新手不友好)
3.(*0)() 我们理解为地址为0的函数指针 但是为0的地址不存在所以要做类型转换
4.将常数0转型为“指向返回值为void的函数指针” (void(*)())0
5.用fp替换(void (*)())0 *((void (*)())0)()
6.用typedef 更清晰的表达 typedef void(*funcptr)(); (*(funcptr)0)();
3.运算符的优先级的问题
运算符很多,不好记
*p++ 同 *(p++) 而不是 (*p)++ *p()同*(p())而不是(*p)() a.b.c 同 (a.b).c
所以我们记住两点:
1.任何一个逻辑运算符的优先级低于任何一个关系运算符
2.移位运算符的优先级要比算术运算符的优先级低,但是比关系运算符要高
4.数组与指针的问题
1.C语言中只有一维数组(C99允许变长数组),数组中的元素可以是任何类型,也可以是数组
2.对于一个数组 ,我们只能够做两件事情:确定数组的大小和获取指向该数组下标为0的元素的指针。其他的操作看似是通过数组下标进行的,实际上是通过指针进行的。
*(a+i) 即数组a中下标为i元素的引用,常用所以简写为a[i]
5.非数组指针
实现字符串的链接
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc ,char** argv) { char *s = "I love"; char *t = "china"; char *r; //*malloc( ) 可以确保有内存空间可以开辟 现在可以忽略 r = malloc(strlen(s)+strlen(t)+1); //+1 是'/0' 字符串结束位 if(!r) { //or NULL == r printf("开辟内存空间失败"); return -1; } strcpy(r,s); strcat(r,t); printf("string r is:%s\n",r); return 0; }