首页 > 代码库 > C与指针——与谭浩强不同的C

C与指针——与谭浩强不同的C

闲来无事,看看《C与指针》。

                             


    如果有人告诉你,马里奥可以用c写出个矩阵的相撞的判断,你也可以写出自己的马里奥的时候,动力就来了。


   其实C可以这样写的!


  


C混乱编码大赛作品,美国 Don Yang(感觉就是个动漫宅)。


    (一)C是自由形式的语言,比较好的编码规范就是:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. two = one + one ;  


其实下面那样自由也是可以的,所以,那个头像不奇怪,你也可以:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. two  
  2. =  
  3. one +  
  4. one  

所以下面也是一样:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int* a;  int *a;  


  (二)三字母词

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int main(int argc, char *argv[])  
  2. {  
  3.     printf("Hello ??(:");  
  4.     return 0;  
  5. }  

你觉得他会显示出一张哭脸吗,不,看,变脸:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. Hello [:请按任意键继续. . .  

这就是三字母词(trigrph),??( 合起来表示 [ 。


    谭浩强老师的书把没编过程序的我带进了编程的世界,打基础的话算很好了,不过后面回来看看,确实有不足的地方。


    其实程序出现的很多int a,b,i,j。问题就存在与变量名的随意,导致以后代码重看的时候忘掉变量是干什么用的,所以命名要注意。不过书作为例子示范,没必要讲究那么多。


  (三)+=和=

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int number;  
  2. number = number +1;  
  3. number += 1;  

两个的效率基本相同。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int number;  
  2. while(1)  
  3.   number++,  
  4.   number++;  

但是,遇到

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. number[3f(x)]=number[3f(x)]+1;  
  2. number[3f(x)]+=1;  

就有区别了,编译器是不知道f(x)的结果的,也不知道每次的结果是不是相同,所以他会计算两次,这样+=就比计算两次的f(x)高效。


 (四), 的妙用

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int number;  
  2. while(1)  
  3.   number++,  
  4.   number++;  


不用{},但是不推荐使用,因为难分辨,还是要有良好的编码风格。


   (五)左值右值问题

所谓的L-value和R-value,L=R,不过l也可以指location,可寻址值,r指read,可读值。

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. a = b + 1;  

b+1是一个值,a有特定的存放地址,可以赋值。但是

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. b + 1 = 1;  

b+1作为可确定的一个值,会存储在一个地方,但是未知,计算机不允许你把值放到一个你未知的地方。


   (六)指针

    计算机里,每个字节(byte)有8位(bit),一个位就是0和1。

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int a = 1;  
  2. int *b = &a;  

假如a的地址为100,那么&a就是取a的地址。

而第二条语句其实也可以这样赋值:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int *b ;  
  2. b = &a;  

b是指向整形的指针变量,将a的地址赋给b,则b存储的是a的地址,*b就是a地址所指向的值,即1。了解这个之后,后面都容易理解。

 

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. *(b+1)  

指的是b指针后的下一个值。

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int a;  
  2. *&a = 1;  
  3. a = 1;  

第三条语句和第二条语句相同吗?是的,相同,只不过第二条书写麻烦。

&a,a的地址,*&a,a的地址所指向的值为1,也就是a的值为1。

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. int main(int argc, char *argv[])  
  4. {  
  5.     int c[5] = {1,2,3,4,8};  
  6.     int *d = &c[4];  
  7.     int *e = &c[1];  
  8.     int f = &c[4];  
  9.     int g = &c[1];  
  10.     printf("%d\n",&c[4]);   
  11.     printf("%d\n",&c[1]);   
  12.     printf("%d\n",*d);  
  13.     printf("%d\n",*e);   
  14.     printf("%d\n",d-e);  
  15.     printf("%d\n",&c[4]-&c[1]);   
  16.     printf("%d\n",f-g);   
  17.     printf("%d\n",c[4]-c[1]);   
  18.     return 0;  
  19. }  


运行结果:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 1245000  
  2. 1244988  
  3. 8  
  4. 2  
  5. 3  
  6. 3  
  7. 12  
  8. 6  
  9. 请按任意键继续. . .  


指针和指针的相减需要两个指针指向同一个数组,其实&c[n]就是一个指针,两个指针相减的结果是两个指针的内存距离除以数组类型的长度,其实就是下标之间的差值。而整型的强制转换之后,就变成了两个整数的差值了,和指针相减没有关系。

++与指针

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. *cp++  //++优先级高于*,cp指针的拷贝指向的值,cp下次的时候指向下一个  
  2. *++cp  //指向cp下一个指针的拷贝所指向的值。  



    (七)动态内存分配,数据结构等等。

先弄清楚C内存分配的部分。栈(编译器自动分配释放,存放函数参数值,局部变量值),堆(由自己分配释放),全局区,文字常量区,程序代码区。

为什么数据结构里都用malloc,就是因为自己想分配多少就多少,掌控空间大小,比较自由。 搞懂这个和指针,数据结构就好办。

    (八)预处理器
define的作用可以将文本替换到程序里。
所谓的宏,define允许把参数替换到文本中,如:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #define double(x)  x*x  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int a = 1;  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. printf("%d",double(a+1));  
double会替换成上面的表达式,但是这里的结果会有问题,因为根据参数代入,那么会等于a+1*a+1,看出来没有,结果不是我们想要的。所以,应该在表达式上加入括号。

还有一个好用的地方。
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #define MAX(a,b)  ((a)>(b)?(a):(b))  
没有类型限制,因为宏是替换的,相当于把代码全部插进去,如果宏比较简单,那还是高效的。

    (九)输入输出流

讲一下EOF这东西,之前没见过。
http://blog.csdn.net/ltx19860420/article/details/5526828
转一篇,其实以前在写getchar和putchar的时候烨觉得很奇怪,为什么不是我们输一个字符打印一个字符,非要回车一下它才显示。

    (十)标准函数库
stdlib.h 里面是有随机数函数的 int rand( void );
也有数学函数的调用库:math.h,
时间函数:time.h。
具体的就不详述了。


    原来谭浩强的c当启蒙书还是挺好的,C与指针就是加强版。

书后推荐:《c++沉思录》《c专家编程》《c陷阱与缺陷》《c++ Templates》

C与指针——与谭浩强不同的C