注册 登录
查看: 3505|回复: 17

C语言杂谈:指针与数组 (上)

[复制链接]
发表于 2015-4-30 10:56:36 | 显示全部楼层 |阅读模式

思维导图


介绍

1> 指针定义:指针是保存变量地址的变量。

2> 本文重点
>> 指针与数组之间的关系
>> 操纵指针的规则

3> 指针优点
>> 表达某个计算的唯一途径
>> 代码更高效,更紧凑

4> 指针缺点:难以理解,但是用好了,代码会非常清晰。

5> 将指针、数组和地址的算术运算集成在一起是C语言的一大优点。

指针与地址

1> 内存组织方式


(1) 内存是一个个单元组成的,每一个内存单元中存放一个字节(8位)的二进制信息。

(2) 机器中的内存单元是有序排列的。

(3) 机器给各个内存单元规定不同地址来管理内存。这样,CPU通过地址来识别不同的内存单元,正确的对内存单元进行操作。


2> 指针与变量的关系(P:是指针变量,C:内存对象)


>>> P:保存C:中的单元首地址——这里的地址不是物理地址,而是经过地址映射后的虚拟地址,即逻辑地址。
>>> P:为指向C:的指针
3>理解指针
>>> 指针占用的内存空间大小: 32位系统占用4byte,64为8byte。
机器配置:
打印指针大小:
>>> 指针就是地址——我们可以把指针认为是用来存放地址的数据类型。不能把指针简简单单的当成一个整型数,虽然地址的值是一个整型数据。
>>> 指针是有类型的,但是这个类型不是给指针分配内存的,而是用来寻址的。

指针与函数参数
1.普通参数:C语言通过传值方式将值传递给被调用函数。
>> 会把变量的值复制一份给被调用函数。
>> 复制:会把变量的值赋值给一个新的变量(参数)——变量和新的变量必须有相同的存储容量。
>> 被调用函数并不能修改主调程序中的变量值,因为被调用函数使用的是一个复制过来的内存单元。
2.指针参数: 本质上跟普通参数传递是相同的,也进行了变量复制,但是传过去的值是地址。 被调用函数通过地址能够访问和修改主调程序中变量的值。
3.参数在内存消耗
普通参数:取决于申明类型。char:1个字节;short:2个字节;long:8个字节
指针参数:指针变量里存储的是地址(一般是4个字节——32位),永远是一个固定长度,不管是什么类型的指针。——除非处理器变化不是32位。
4.double *dp, atof(char *) 这里的dp是指针变量,而atof是函数

指针与数组
1.指针操作数组快于下标操作数组
2.数组的空间分配.如int a[10];——会在空间分配出40个相邻的内存单元来(10*4)。

3.指针操作数组
int *pa;
pa = &a[0];

4.指针移动
int *pa;
int a[10];
pa = &a[0];
pa+1将指向下一个元素a[1]:
>> 内存中的变化:”指针加1″会根据指针指定的类型int移动4个内存单元,其实本身并没有移动,只是pa+1等于第5个内存单元地址——“指针加1”中的1的大小是取决于pa的类型int的,指针类型决定指针跨内存单元的步长。
>> pa+1 等于是指向第5个内存单元——a[1]的第一个内存单元。
5.规则:
>> &a和a+i含义相同,相互使用。a+i是a之后第i个元素地址。
>> 数组名代表数组第一个元素的地址。

地址运算符
1. 指针初始化:0或表示地址的表达式。
2. “指针加1”中的“1”的大小根据数据类型的长度按比例缩放。如果int类型占4个字节的存储空间,对应的1按4倍计算。

验证:
>>> 若指向char类型的指针p的内存地址是0×000000,那么p+1后的地址是0×000001。
验证过程如下:
运行结果:

>>> 若指向int 类型的指针p的内存地址是0×000000,那么p+1后的地址是0×000004。
运行结果:
3.指向不同数组的元素的指针之间的算术或比较运算都没有定义。
4.指针相减:如果p和q指向相同数组中的元素,且p 16/4=4 (按照int型所占内存单元等比例缩放) => 4 + 1 = 5;

总结
这次写关于c语言方面指针,是因为这两天看php内核文件的时候,由于C方面的欠缺,所以看着很吃力。所以想再复习下C语言。
为什么从指针入手呢?可能是因为指针在C语言中是比较难的。所以先把最难的啃下来。
本来是想一次性写完,可是指针这方面内容太多,所以决定分几批写。
我在C语言方面还是很薄弱,如果文章中有错误,希望高手们指点下。
参考文献:《C程序设计语言》

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

本帖被以下淘专辑推荐:

回复

使用道具 举报

 楼主| 发表于 2015-4-30 11:01:00 | 显示全部楼层
思维导图


介绍前接上文C 杂谈之 指针与数组 (一),接续往下谈指针和数组。

指针与数组 ——承接上文进行扩展你知道X = Y,在编译运行过程中,是什么样吗?


字符指针与函数1> 字符串是一个以”结尾的字符数组。
看一个例子:printf接受的是一个指向字符数组第一个字符的指针。

这个例子与下面两个代码是一个道理.



2> 几个常用字符函数的编写。
1>>> strcat(s,t)函数,把t指向的字符复制到s指向的字符后面?——注意”

  1. #include
  2. #include

  3. /*  strcat(ps, t): Copy the charactor pointed
  4. *  by t  append to the character pointed by s  
  5. */
  6. void *strcat(char *ps, char *t){
  7.     char *addr = ps;
  8.     assert((ps != NULL) && (t != NULL));
  9.     while(*ps){  /*  The s point to the last character   */
  10.         ps++;
  11.     }

  12.     while(*ps++ = *t++){ /*  Copy t append to the s*/
  13.     }

  14.     return addr;
  15. }

  16. int main(){
  17.     char s[5] =  "AB";
  18.     char *t = "E";
  19.     printf("%s", strcat(s, t));
  20.     return 0;
  21. }




注意:在strcat里的两个指针ps和t,方法结束后,这两个函数都指向”后面,因为ps++操作是”先取结果,后自增”
内存变化:


2>>> 函数strend(s,t):字符串t出现在字符串s的尾部,返回1,否则返回0。


  1. int strlen(char *p){
  2.     int iLen = 0;
  3.     while(*p){
  4.         iLen++;
  5.         p++;
  6.     }   




  7.     return iLen;
  8. }




  9. /*  strend:find t in s  */
  10. int strend(char *s, char *t){
  11.     int sLen = strlen(s);
  12.     int tLen = strlen(t);




  13.     if(tLen > sLen) return 0;




  14.     while(*s)
  15.         s++;




  16.     while(*t)
  17.         t++;




  18.     for(;tLen--;){
  19.         if(*--t != *--s) return 0;
  20.     }   




  21.     return 1;
  22. }




  23. int main(){
  24.     char *s = "Hell Wold , Chuanshanjia";
  25.     char *t = "Chuanshanjia";




  26.     printf("%d", strend(s, t));
  27.     return 0;
  28. }




3>>> strncpy(s,t,n) 将t中前n个字符复制到s中。

  1. strncpy(s,t,n)
  2. #include

  3. int strlen(char *p){
  4.     int i = 0;
  5.     while(*p){
  6.         p++;
  7.         i++;
  8.     }   

  9.     return i;
  10. }

  11. /*  t中最多前n个字符复制到s中   */
  12. char *strncpy(char *s, char *t, int n){
  13.     char *addr = s;
  14.     if(!strlen(s) || !n) return 0;

  15.     int tLen = strlen(t);
  16.     if(!tLen) return 0;

  17.     if(tLen < n)
  18.         n = tLen;

  19.     // Move the pointer s to the last
  20.     while(*++s) ;

  21.     while(n--){
  22.         *s++ = *t++;
  23.     }   

  24.     return addr;

  25. }

  26. int main(){
  27.     char s[20] = "Hell World ";
  28.     char *t = "Chuanshanjia";

  29.     printf("%s", strncpy(s, t, 2222));
  30.     return 0;
  31. }




命令行参数1.第一个参数(常用argc表示)(:运行时命令行参数数目;第二个参数(常用argv表示)是一个指向字符串数组的指针。
2.C语言规定,argv[0],表示启动程序的名称。
3.实例

运行结果:

内存分配:

解释:
>> argv是一个指向指针数组的指针。
所以接受参数也可以写成:

结合上图,我们可以这样理解:从里向外看

复杂声明1.阅读——从右向左规则。
>> 规则符号:
———————————————————–
* 读作”指向…的指针”
[] 读作”…的数组”
() 读作”返回…的函数”
———————————————————–
下面两个示例:
int *f() ; // f: 返回指向int型的指针
>>步骤:
1)找标识符f:读作”f是…”
2)向右看,发现”()”读作”f是返回…的函数”
3)向右看没有什么,向左看,发现*,读作”f是返回指向…的指针的函数”
4)继续向左看,发现int,读作”f是返回指向int型的指针的函数”

int (*pf)(); // pf是一个指针——指向返回值为int型的函数
1)标识符pf,读作“pf是…”
2)向右看,发现),向左看,发现*,读作 “pf是指向…的指针”
3)向右看,发现”()”,读作“pf是指向返回…的函数的指针”
4)向右看,没有,向左看发现int,读作”pf是指向返回int型的函数的指针”

总结我最近着重看C,是因为我想深入了解一下PHP内核语言和服务器模块开发。现在的C语言,能够让我更深入的了解计算机内部。
原文出处:http://blog.jobbole.com/86412/



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 1 反对 0

使用道具 举报

发表于 2015-5-2 11:41:45 | 显示全部楼层
ii童话Bū说话 发表于 1430538008
我想知道那个C的软件是什么!挺炫的!高亮不错
ubuntu里面的编辑软件
来自PC客户端 来自PC客户端
回复 支持 1 反对 0

使用道具 举报

发表于 2015-5-2 11:40:08 | 显示全部楼层
我想知道那个C的软件是什么!挺炫的!高亮不错
回复 支持 反对

使用道具 举报

发表于 2015-5-2 14:33:19 | 显示全部楼层
仰逸致 发表于 2015-5-2 11:41
ubuntu里面的编辑软件

linux操作系统里面的软件呀!
回复 支持 反对

使用道具 举报

发表于 2015-5-11 22:27:39 | 显示全部楼层
很好
回复 支持 反对

使用道具 举报

发表于 2015-10-2 01:49:12 | 显示全部楼层
先藏起来
回复 支持 反对

使用道具 举报

发表于 2015-12-9 20:58:27 | 显示全部楼层
谢谢,学习了
回复 支持 反对

使用道具 举报

发表于 2015-12-17 16:57:19 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2016-3-10 09:42:42 | 显示全部楼层
学习了,前几天刚把C语言又学了一遍,重新加强记忆。
回复 支持 反对

使用道具 举报

发表于 2016-6-30 21:33:37 | 显示全部楼层
啥时候讲链表啊?坐等。课本里面动态链表没看懂……
回复 支持 反对

使用道具 举报

发表于 2016-7-3 11:14:35 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

发表于 2016-7-19 21:24:15 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

发表于 2016-10-17 20:51:53 | 显示全部楼层
可以的
回复 支持 反对

使用道具 举报

发表于 2016-10-20 19:55:51 | 显示全部楼层
谢谢,辛苦,学习了
回复 支持 反对

使用道具 举报

发表于 2016-10-23 11:22:17 | 显示全部楼层
  听不错的!!
回复 支持 反对

使用道具 举报

发表于 2017-8-12 23:09:59 | 显示全部楼层
C语言中的高级用法都比较抽象,需要有一定的逻辑分析能力,所以最好是通过实例来强化对C语言的理解
回复 支持 反对

使用道具 举报

发表于 2017-9-15 23:11:57 | 显示全部楼层
试试先
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回列表 返回顶部