指针---C语言的灵魂

  很多朋友在初学C语言的时候,难免都会在指针这块停留许久,包括我本人。久久不能释怀,对其爱恨交织。静下心来,想总结一下自己在学指针的时候的一点心得,也是第一次写博客,激动万分,希望朋友们能多多指正、多多批评!

  首先呢,针对指针,给初学指针的朋友一个最感性的认识:所谓指针,指的是,一个量,是一个储存的内容是地址的一个量,这个概念包含两个点:

  一、指针是个量,对应着一块内存区域;

  二、指针存储的信息是某个内存单元的地址。

  如上图所示,为了存储32位的地址数据,指针占据了4个字节,每个字节8个二进制位,该指针中存储的是某个类型在内存的地址数据,此处以double类型为例,double类型的数据占据8个内存字节,将其首字节的地址存储在指针中,这样,通过指针可以访问该double数据。这类似于现实生活中的地址和名片,习惯于把地址印在名片上,这里名片的作用和指针相同,存储的都是地址数据。

  很明显, 在引入指针的时候,多次提到了内存,那么很自然地,接下来先简单说一下内存的一些概念!

  关于内存

  大家都知道,内存是平时接触较多的一个概念,从硬件上说,内存是一个物理设备,从功能上讲,内存是一个数据仓库,程序在执行前都要装载到内存中才能被中央处理器(CPU)执行。

  1、计算机中的内存

  以Windows系统为例,执行安装在硬盘上的某个程序,实际上是将该程序的指令和数据读入内存,供CPU执行的过程。内存是由按顺序编号的一系列存储单元组成的,在内存中,每个存储单元都是唯一的地址,通过地址可以方便地在内存单元中存取信息。内存中的数据要靠电源维持,当计算机关机或者意外断电时,其中的所有数据就永远消失了。

  2、内存地址

  内存地址的引入是同样的道理,为了正确访问每个内存单元,要对其进行编址,以32位计算机为例,其地址空间为32位,采用32为地址编码,诸如0X87654321的形式。内存地址是连续的,相邻内存单元空间的地址差1,可以把内存看成一个平坦连续的一维空间。

  3、内存中保存的内容

  在计算机中,以二进制数据的形式存放的,每个内存单元的容量是1B,即8bit。内存是CPU唯一可以直接访问的大容量设备,使用Windows的朋友都清楚,双击某个可执行的程序,CPU会执行它,这实际上是复杂的内存载入过程:

    ① 程序所要进行操作的对应代码装载到代码区

    ② 全局和静态数据等装载到数据区

    ③ 开辟堆栈、供临时变量等使用

   4、内存与操作系统

   程序在运行前,需要向操作系统申请存储空间,在内存空间足够空闲的时候,操作系统将分配一段内存空间并将外存中软件拷贝一份到内存中,并启动软件运行,在运行期间,该软件分配的空间不再分配给其他软件,当软件运行结束后,将回收该软件内存空间(但并不清楚遗留数据,Java局部变量必须初始化,原因就在此,防止被之前的遗留数据影响)

  扯了这么多内存的内容,只是为了让初学的朋友有点感觉,也是为学习指针打一剂预防针!

  关于指针

  指针就是地址,地址就是指针。

  指针变量是存放内存单元地址的变量

  指针的本质是一个操作受限 的非负整数

  下面从两个方面来浅谈一下指针的问题:

  1、基本类型的指针

    指针的定义:类型 * 指针变量名;

    比如int * p; double * q;

 1 include<stdio.h>
 2 int main() {
 3     int *p;
 4     int i = 10;
 5     int j;
 6     // j = *p;
 7     // p = &i;
 8     // *p = i   < ->   i = i
 9     // j = *p;
10     // char ch = ‘a‘;
11     // p = &ch   /*类型不一致 错*/
12     // printf("i = %d,j = %d,*p = %d",i,j,*p);// 10 10 10
13     return 0;
14 }

在上面的代码3~5行定义了三个变量(如下图),分别是:int *形的变量p、int形的变量i、int形变量j。需要清楚的是在第三行中,p是变量名字,int * 表示该变量只能存储int类型变量的地址。

  如果在指针变量声明之初确实不知道将此指针指向何处,最简单的方式是将其置为“0”,C语言中提供了关键字NULL: int * pInt = NULL;

如果放开第6行注释。会出现什么结果呢,势必会报错!因为*p保存的是地址,但这句话上面的代码中并没有给p赋值。p不知道哪个单元的,p指向的是一个不确定单元,垃圾数据!如果放开第9行就不会有这种结果了,因为在第7行对p进行了赋值,p变量保存了i的地址了!

在第七行中,有三句话:

      ① p保存了i的地址值,p指向了i。

      ② 但并不说明p等于i或者说i等于p。修改i的值并不影响p的值,修改p的值也不影响i的值。

      ③ i能代表什么,*p就能代表什么。(如第8行)

再看第10~11行,这个赋值对吗?定义一个char类型字符,将他的地址保存在整形指针p中,毫无疑问,这也是错的,前面已经说了,int * 表示该变量只能存储int类型变量的地址。

接下来再看指针在函数中的作用:

 1 #include<stdio.h>
 2
 3 void f(int i)
 4 {
 5     i = 100;
 6 }
 7
 8 int main(void)
 9 {
10     int i = 5;
11     f(i);
12     printf("%d\n",i);
13     return 0;
14 }

 1 #include<stdio.h>
 2 void f(int * p) // 不是定义一个名字叫*p的形参,而是定义了一个p的形参,它的类型是int
 3 {
 4     *p = 100;
 5 }
 6
 7 int main(void)
 8 {
 9     int i = 5;
10     f(&i);
11     printf("%d\n",i);
12     return 0;
13 }

在第一个代码中,如果想通过函数改变i的值,能成功吗?很明显是不行的,i是局部变量,i输出的最终值将仍是5。

那么如何根据被调函数改变主调函数的值呢,第二段代码就实现了这个问题,通过使用”*指针”的形式,可以直接访问指针所指向的内存空间。换言之,因为通过参数传递,p保存了i的地址,那么*p 就等价于i,同时可以通过间接引用“*p = 100;”可以改写指针指向的区域!注意在第二段代码中的第二行,形参为 int * p ,不是定义一个名字叫*p的形参,而是定义了一个名字为p的形参,它的类型是int *!

2、指针与数组的关系

  首先要明白,数组名就是一个指针,并且指向数组的首地址!数组元素的地址是连续的。

  数组名的含义:

    ① 是一个指针变量

    ② 存放的是一维数组第一个元素的地址

    ③ 值不能改变

    ④ 指向第一个元素

  下标和指针的关系:

    a[i] = *(a+i)

 1 #include<stdio.h>
 2 void printArray(int * p,int len) {
 3     p[2] = -3;
 4     /* p[0] = *p      p[2] == *(p+2) == *(a+2) == a[2]
 5          p[i]就是主函数的a[i]
 6     */
 7     int i = 0;
 8     for(i = 0; i<len; ++i) {
 9         printf("%d\n",p[i]);
10     }
11 }
12 int main(void)
13 {
14     int arr[5] = {1,2,3,4,5};
15     printArray(arr,5);
16         return 0 ;
17 }

  有了上面的理论再看这段代码,就不难理解,p[0] = * p;的含义了,因为数组名是一个指针,指向数组第一个元素的地址,所以数组的第一个元素p[0]就等同于*p了!

  因为"a[i] = *(a+i)",可以知道p[2] == *(p+2),因为p指向第一个元素,那么p+2就自然指向第三个元素了,所以p[2] = 3是给数组的第三个元素赋值,这事没问题的!但注意*(p+2)不等同于*p+2,后者是在*p指向的元素上,给这个元素的值加上2,前者并非如此,而是给他的地址“+2”。

  今天就先到这里,指针的内容多多,日后还应继续总结,继续和大家讨论!

  初次写博,纰漏多多!望朋友们不吝赐教!

  

原文地址:https://www.cnblogs.com/mvcq/p/8640798.html

时间: 2024-08-04 11:10:22

指针---C语言的灵魂的相关文章

C指针——C语言手记

最近写程序的时候,发现自己很多东西都开始忘了.今天终于有机会好好总结一下指针,当做个笔记同时也希望对大家有用.如果有不正确的地方,希望大家能帮我指正一下.然后我的实验环境是32位RHEL+eclipse. 一.指针基本属性 指针的属性主要包括指针的类型.指针所指向的类型.指针的值.下面以一个简单的例子为例 int *p: 指针的类型:int * 指针所指向的类型:int 指针的值(指针所指向内存区的地址):野指针 总结一下,指针的类型:去掉变量名字之后的那一部分 指针所指向的类型:去掉*变量名之

【转】C语言:指针,C的灵魂

共八章内容. 第一章.指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区.让我们分别说明. 先声明几个指针放着做例子: 例一: (1)int *ptr; (2)char *ptr; (3)int **ptr; (4)int (*ptr)[3]; (5)int *(*ptr)[4]; 如果看不懂后几个例子的话,请参阅我前段时间贴出的文章<<

C++基础 (8) 第八天 数组指针 模板指针 C语言中的多态 模板函数

1昨日回顾 2 多态的练习-圆的图形 3多态的练习-程序员薪资 4员工管理案例-抽象类和技术员工的实现 employee.h: employee.cpp: technician.h: technician.cpp: source.cpp: 5员工管理案例-销售和经理实现 修改employee.h: displayStatus不用虚函数了 salesman.h: salesman.cpp: manager.h: manager.cpp: 6员工管理案例-销售经理的实现 7 中午回顾 注意: 多继承

原型模式 -- JavaScript语言的灵魂

原型模式就是将原型对象指向创建对象的类,使这些类共享原型对象的方法与属性.JS是基于原型链实现对象之间的继承,是对属性或者方法的共享,而不是对属性和方法的复制. // 图片轮播类 var LoopImages = function (imgArr, container) { this.imagesArray = imgArr; this.container = container; } LoopImages.prototype = { // 创建轮播图片 createImage:function

真正明白c语言二级指针

指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的"值,结果传递"等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的指针.....n级指针就是.... p *p **p                                      --- --- ----                                      | |->| |->| |            

嵌入式Linux C语言(二)——指针

嵌入式Linux C语言(二)--指针 指针是C语言中广泛使用的一种数据类型,是C语言的灵魂.指针提供了动态操控内存的机制,强化了对数据结构的支持,而且实现了访问硬件的功能.学习指针是学习C语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志. 一.指针的概念 在计算机中,所有的数据都是存放在内存中的,一般把内存中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不一样,如int占用4个字 节,char占用1个字节.为了正确地访问内存单元,必须为每个内存单元编上号.

C语言编程入门——指针(上)

指针,是C语言的灵魂,也是C语言与其他高级编程语言不同的地方,它可以灵活的操作内存,同样,也会带来很多问题,需要安全的使用指针. 指针变量是指存放变量地址的变量,刚开始学可能会有点困难,需要多多理解. 指针常见错误1: # include <stdio.h> int main(void) { int * p; //定义int类型变量指针p int i = 3; *p = i; //此语句错误,*p未初始化,p存放了未知的地址,指向了未知的变量,如果被i修改,则会导致错误. printf(&qu

C语言中多级指针的重点分析

一.指针简介        指针是C语言的灵魂,C语言之所以强大,很大一部分原因在于对指针的灵活运用.我们无论需要对内存的精准分配和释放,还是对接口api的使用,乃至面向对象中的类和对象的封装,都涉及到了指针.C语言的指针大致可以分为两种,一种是作为一个变量,其保存的是一段内存地址,也就是本文要谈的多级指针:另一种是作为一种数据类型,像函数指针,用于引出一种类型,主要用于回调函数. 二.指针与基础数据类型 从内存的角度看,数据类型就是一段固定大小内存块的别名. int a=0; int在32/6

C语言-指针入门

指针被称为"C语言的灵魂".实际上是一种专门用于保存内存地址的变量. 1.定义一个指针 在C语言中,我们使用形如int *p;的语句来声明一个指针,其中int可以替换成char,double等基础数据类型,跟在p前面的*表明p是一个指针类型的变量.但在程序编写过程中,这样仅声明指针却不进行初始化是非常危险的,这类指针通常被称为"野指针".因此推荐在声明的同时便对指针进行初始化: int i = 10; int *p = &i; // 用p保存i的内存地址 可