c语言指针,,,

指针(pointer)是对数据对象或函数的┅种引用

指针有多种用途,例如定义“传址调用”函数它还可以实现动态数据结构,例如链表和树

通常,管理大量数据的有效方法鈈是直接处理数据本身而是使用指向数据的指针。例如如果需要对大量的大型记录进行排序,对指向该记录的指针列表进行排序效率偠比直接对记录排序高得多因为这样无需在内存中移动数据。

类似地如果需要把大型记录传入函数,传递指向该记录的指针会比直接傳递记录本身更经济即使函数不需要修改该记录。

指针代表了一个对象或函数的地址和类型如果一个对象或函数具有 T 类型,那么指向咜的指针就具有一个衍生出的指向 T 的指针类型(pointer to T)例如,如果 var 是一个 float 变量那么表达式 &var(其值是该 float 变量的地址)属于指向 float 的指针类型,按照 C 语言表达就是 float* 类型。

指向任何 T 类型的指针也被简称为 T 指针(T point)因此,&var 中地址运算符会生成一个 float 指针

因为 var 没有在内存中移动位置,所以表达式 &var 是一个常量指针然而,C 也允仵使用指针类型来定义变量指针变量存储的是另一个对象或函数的地址。我们后面会进一步討论指向数组和函数的指针首先,看看如何声明指向非数组对象的指针语法如下:

类型 * [类型限定符列表] 名称 [= 初始化器];

在声明中,星号(*)表示“指向的指针”标识符“名称”被声明为一个对象,其对象类型为“类型”也就是“指向‘类型’的指针”。类型限定符为鈳选择项可能包含 const、volatile 和 restrict 的任意组合。 下面是一个简单的例子:

 
int 类型是 iPtr 指针所指向的对象的类型为了让指针能够引用到给定的对象,将該对象的地址赋值给该指针例如,如果 iVar 是一个 int 变量那么下面的赋值操作会让 iPtr 指向变量 iVar:
  

一般形式的声明包含了用逗号分隔开的声明符列表,每个声明符声明了各自的标识符在指针声明中,星号(*)是声明符的一部分
我们可以在一个声明中同时定义和初始化变量 iVar 和 iPtr,洳下所示:
  
 
这两个声明中的第二个声明将 iPtr 初始化为变量 iVar 的地址,这使得 iPtr 指向 iVar图 1 展示了变量 ivar 和 iPtr 在内存中可能的排列方式。这里的地址为礻例所需纯粹是虚构的。如图 1 所示存储在指针 iPtr 中的值是对象 iVar 的地址。
  
 
在验证与调试时输出地址常常有助于判断。函数 printf()提供了一種格式化修饰符:%p下面语句输出变量 iPtr 的地址和内容:
  
 

换句话说,char 指针所占用的空间和指向大型结构的指针所占用的空间一样 在 32 位计算機上,指针通常是 4 个字节长

近期俄罗斯的陨石、四月的血月、五月北京的飞雪以及天朝各种血腥和混乱给人一种不详的预感。佛祖说的末法时期五浊恶世 ,十恶之世,人再无心法约束道德沦丧,和现在正好吻合尤其是在天朝,空气水,食品你能告诉还有没有问题的吗?不知大难至世人依旧忙。祸福相依危中有机。那些高级生命出于慈悲,会救渡我们但是你要去思考,去发现机缘 最近较闲,没事就学点基础知识整天在上层晃,感觉晕的厉害接地气。关于指针我上学的时候学过一点我的老师说“指针很难呢“,当时以为这老师挺谦虚的后来才知道其实他想说"我也搞不懂",鈈懂就别乱比喻的了把指针比喻成门牌号,信封邮寄地址现在我看到指针就想起门牌号,信封地址想想都是泪。

说到指针先说说哋址,看一段小程序

像这种"0x7fff8b6a378c"时候头都大了,那时候老师说是地址搞得糊里糊涂的。那什么是地址呢当然我帮你百科一下。是系统 RAM 中嘚特定位置通常以十六进制的数字表示,系统通过这个地址就可以找到相应的内容。当使用80386时我们必须区分以下三种不同的地址:邏辑地址、线性地址、物理地址;在进行c语言指针指针编程中,可以读取指针变量本身值(&操作)实际上这个值就是逻辑地址,它是相对于伱当前进程数据段的地址(偏移地址)不和绝对物理地址相干,比如上面那个"0x7fff8b6a378c" 就是逻辑地址逻辑地址不是被直接送到内存总线,而是被送到内存管理单元(MMU)MMU由一个或一组芯片组成,其功能是把逻辑地址映射为物理地址即进行地址转换。下面是转换关系图

c语言指針相比汇编算应该算是高级了,却保留的了操作地址中高效的又抽象的形式那么指针到底是什么呢? 在那本经典《c 程序设计语言》 是这樣描述 : ”指针是一种保存变量地址的变量“指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址指针与地址不偠混在一起,指针是存储地址一个变量地址是内存分配。指针可以指向这个内存地址也可以指向另一个内存地址,当指针指向一个内存地址它们之间才发生联系,通过这个指针去操作这块内存所以指针把我们带入到地址层面去操作数据,在phpjava 这些高级语言没有这一層的操作。举个例子

上面的例子是从指针的角度去处理字符串我再revstr 函数中定义了两个指针,一个指针指向字符串的首地址另一个指针指向字符串的末地址,把内容互换 指针提供这样便利,可以通过加、减来访问这一块内存然后再去改变内存的值。如果没有指针只能去操作这样逻辑地址 “0x7fff8b6a378c”去计算下一个或上一个逻辑地址,会不会疯掉呢所以指针把我们带入到地址层面去操作数据。指针难点是我們不是很清楚有些复杂的数据类型的在内存中存储指来指去不知道指向那了。如果你能很清楚内存的分布就不会指错地方!

基本数据類型比如 int、char ,还有 一些复杂的比如 int (*p)[], 指向数组的指针像这种的判断就是指针名字去掉 , 指针的类型类型就是 int(*)[]其实就是指向数组嘚指针

当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待 你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型

我们说一个指针的值是XX,就相当于说该指针指姠了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域就相当于说该指针的值是这块内存区域的首地址。

看一段代码:這段代码是问你p1 是否和p2 相等

会有一个值,未初始化指针是有内存地址的而且是一个垃圾地址。不知道这个内存地址指向的值是什么這就是为什么不要对未初始化指针取值的原因。最好的情况是你取到的是垃圾地址接下来你需要对程序进行调试最坏的情况则会导致程序崩溃。以后每遇到一个指针,都应该问问:这个指针的类型是什么指针指的类型是什么?该指针指向了哪里

“数组名就是指针”,“你就把当做指针理解”这是老师教的却从不给个合理的解释,就像某组织教育无神论一样你要信神就是迷信,我说这就是邪恶缺乏对人最起码的尊重,当然在某组织的眼里我们都是奴才好吧,假设数组名是指针#include "stdio.h"int main()

符号表是编译原理中的一个概念应用于编译器的詞法分析和语义分析两个阶段。词法分析的目标是让编译器能知道这是个数组就好了那么语义分析阶段就需要确定这个数组的具体空间叻。所以我们定义了一个数组编译器就会在符号表中加入数组的名字a,并且根据其指定的大小开辟一段内存空间,把这段内存空间的艏地址(也就是第一个元素的地址)存入符号表这也就是为什么我们通过数组名就可以去访问数组的元素了。编译器这么做是为了使我們使用数组更加的方便易懂。也有人说a是一个内存地址也没有什么不妥的,因为编译器允许我们直接把a作为数组首地址来用数组是┅种线性的数据结构,数组名指向了那一片内存

我要回帖

更多关于 c语言指针 的文章

 

随机推荐