1. 云栖社区>
  2. PHP教程>
  3. 正文

C 杂谈之 指针与数组

作者:用户 来源:互联网 时间:2017-12-01 19:14:26

指针数组杂谈

C 杂谈之 指针与数组 - 摘要: 本文讲的是C 杂谈之 指针与数组, 思维导图 介绍 1> 指针定义:指针是保存变量地址的变量。 2> 本文重点 >> 指针与数组之间的关系 >> 操纵指针的规则 3> 指针优点 >> 表达某个计算的唯一途径 &

思维导图


C 杂谈之 指针与数组-


介绍


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


2> 本文重点


>> 指针与数组之间的关系


>> 操纵指针的规则


3> 指针优点


>> 表达某个计算的唯一途径


>> 代码更高效,更紧凑


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


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


指针与地址


1> 内存组织方式


C 杂谈之 指针与数组-


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


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


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


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


C 杂谈之 指针与数组-


>>> P:保存C:中的单元首地址——这里的地址不是物理地址,而是经过地址映射后的虚拟地址,即逻辑地址。


>>> P:为指向C:的指针


3>理解指针


>>> 指针占用的内存空间大小: 32位系统占用4byte,64为8byte。


机器配置:


C 杂谈之 指针与数组-


打印指针大小:


C 杂谈之 指针与数组-


C 杂谈之 指针与数组-


>>> 指针就是地址——我们可以把指针认为是用来存放地址的数据类型。不能把指针简简单单的当成一个整型数,虽然地址的值是一个整型数据。


>>> 指针是有类型的,但是这个类型不是给指针分配内存的,而是用来寻址的。


指针与函数参数


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)。


C 杂谈之 指针与数组-


3.指针操作数组



int*pa;

pa = &a[0];



C 杂谈之 指针与数组-


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]的第一个内存单元。


C 杂谈之 指针与数组-


5.规则:


>> &a[i]和a+i含义相同,相互使用。a+i是a之后第i个元素地址。


>> 数组名代表数组第一个元素的地址。


地址运算符


1. 指针初始化:0或表示地址的表达式。


2. “指针加1”中的“1”的大小根据数据类型的长度按比例缩放。如果int类型占4个字节的存储空间,对应的1按4倍计算。


C 杂谈之 指针与数组-


验证:


>>> 若指向char类型的指针p的内存地址是0x000000,那么p+1后的地址是0x000001。


验证过程如下:


C 杂谈之 指针与数组-


运行结果:


C 杂谈之 指针与数组-


>>> 若指向int 类型的指针p的内存地址是0x000000,那么p+1后的地址是0x000004。


C 杂谈之 指针与数组-


运行结果:


C 杂谈之 指针与数组-


3.指向不同数组的元素的指针之间的算术或比较运算都没有定义。


4.指针相减:如果p和q指向相同数组中的元素,且p

代码验证:


C 杂谈之 指针与数组-


运行结果:


C 杂谈之 指针与数组-


流程变化:q-p=16 => 16/4=4 (按照int型所占内存单元等比例缩放) => 4 + 1 = 5;


总结


这次写关于c语言方面指针,是因为这两天看php内核文件的时候,由于C方面的欠缺,所以看着很吃力。所以想再复习下C语言。


为什么从指针入手呢?可能是因为指针在C语言中是比较难的。所以先把最难的啃下来。


本来是想一次性写完,可是指针这方面内容太多,所以决定分几批写。


我在C语言方面还是很薄弱,如果文章中有错误,希望高手们指点下。


我知道博客园C方面高手非常多,我在C方面属于菜鸟级别的,没有任何开发经验,所以希望高手们能多指点下!

思维导图

C 杂谈之 指针与数组-


介绍


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


指针与数组 ——承接上文进行扩展


你知道X = Y,在编译运行过程中,是什么样吗?


C 杂谈之 指针与数组-


字符指针与函数


1> 字符串是一个以'/0'结尾的字符数组。


看一个例子:printf接受的是一个指向字符数组第一个字符的指针。


C 杂谈之 指针与数组-


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


C 杂谈之 指针与数组-


C 杂谈之 指针与数组-


2> 几个常用字符函数的编写。


1>>> strcat(s,t)函数,把t指向的字符复制到s指向的字符后面?——注意'/0'


#include
#include
/*strcat(ps, t): Copy the charactor pointed
*by tappend to the character pointed by s
*/
void *strcat(char *ps, char *t){
char *addr = ps;
assert((ps != NULL) && (t != NULL));
while(*ps){/*The s point to the last character */
ps++;
}
while(*ps++ = *t++){ /*Copy t append to the s*/
}
return addr;
}
int main(){
char s[5] ="AB";
char *t = "E";
printf("%s/n", strcat(s, t));
return 0;
}

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


C 杂谈之 指针与数组-金玉岚


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


int strlen(char *p){
int iLen = 0;
while(*p){
iLen++;
p++;
}
return iLen;
}
/*strend:find t in s*/
int strend(char *s, char *t){
int sLen = strlen(s);
int tLen = strlen(t);
if(tLen > sLen) return 0;
while(*s)
s++;while(*t)
t++;
for(;tLen--;){
if(*--t != *--s) return 0;
}
return 1;
}
int main(){
char *s = "Hell Wold , Chuanshanjia";
char *t = "Chuanshanjia";
printf("%d/n", strend(s, t));
return 0;
}

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


strncpy(s,t,n)
#include
int strlen(char *p){
int i = 0;
while(*p){
p++;
i++;
}
return i;
}
/*t中最多前n个字符复制到s中 */
char *strncpy(char *s, char *t, int n){
char *addr = s;
if(!strlen(s) || !n) return 0;
int tLen = strlen(t);
if(!tLen) return 0;
if(tLen < n)
n = tLen;
// Move the pointer s to the last
while(*++s) ;
while(n--){
*s++ = *t++;
}
return addr;
}
int main(){
char s[20] = "Hell World ";
char *t = "Chuanshanjia";
printf("%s/n", strncpy(s, t, 2222));
return 0;
}

命令行参数


1.第一个参数(常用argc表示)(:运行时命令行参数数目;第二个参数(常用argv表示)是一个指向字符串数组的指针。


2.C语言规定,argv[0],表示启动程序的名称。


3.实例


C 杂谈之 指针与数组-


运行结果:


C 杂谈之 指针与数组-


内存分配:


C 杂谈之 指针与数组-

解释:


>> argv是一个指向指针数组的指针。


所以接受参数也可以写成:


C 杂谈之 指针与数组-


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


C 杂谈之 指针与数组-

复杂声明


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语言,能够让我更深入的了解计算机内部。


参考文献:《C程序设计语言》

以上是云栖社区小编为您精心准备的的内容,在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索指针 , 数组 杂谈 ,以便于您获取更多的相关知识。

弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率

40+云计算产品,6个月免费体验

稳定可靠、可弹性伸缩的在线数据库服务,全球最受欢迎的开源数据库之一

云服务器9.9元/月,大学必备