前言

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

地址

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

#include "stdio.h"

int main()
{
int a = ;
int *p = &a;
printf("%p\n", p);
return ;
} // output
0x7fff8b6a378c

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

  关于内存地址怎么转换可以参考一下的博文。《再论逻辑地址、线性地址》、 《我理解的逻辑地址、线性地址、物理地址和虚拟地址

指针

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

#include "stdio.h"
#include "string.h" void revstr(char *); int main()
{
char str[] = "Zhen Shan Ren is good!";
revstr(str);
puts(str);
} void revstr(char *str)
{
char *start, *end, temp;
start = str;
end = start + strlen(str) -;
while (start++ < end--) {
temp = *start;
*start = *end;
*end = temp;
}
}

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

指针的几个概念

 1.指针的类型

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

   2.指针所指向的类型

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

例如:int*ptr:指针所指向的类型是int   int(*ptr)[3]:指针所指向的的类型是int()[3]

   3.指针的值

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

看一段代码:

#include "stdio.h"

int main()
{
char *p1,*p2,*p3;
char ch[] = {'a', 'b', 'c'};
char **pp;
p1 = ch;
pp = &ch;
p2 = *pp; if (p1 == p2) {
printf("p1 == p2\n");
} else {
printf("p1 != p2\n");
} printf("p3 = %p", p3);
return ;
}

这段代码是问你p1 是否和p2 相等?  结果是

//p1 != p2

//p3 = 0x4005f0dxy

&ch  指针类型为 char[3], 当运行到p1== p2 时候,编译器会骂你 “warning: assignment from incompatible pointer type” 指针类型不匹配,看一下p3 会有一个值,未初始化指针是有内存地址的,而且是一个垃圾地址。不知道这个内存地址指向的值是什么。这就是为什么不要对未初始化指针取值的原因。最好的情况是你取到的是垃圾地址接下来你需要对程序进行调试,最坏的情况则会导致程序崩溃。以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指的类型是什么?该指针指向了哪里?

还有一个题目可以试试

#include "stdio.h"

int main()
{
int a[] = {,,,,};
int *p = (int *)(&a+);
printf("%d,%d", *(a+), *(p-));
}

答案在此

指针与数组

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

#include "stdio.h"

int main()
{
int a[] = {,,,};
int *p = a;
printf("a = %d, p =%d", sizeof(a), sizeof(p));
}
//output
//a= 16,p=4

  从输出结果看两者根本就是两个事物,只能说数组名神似指针,数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组;那么数组名到底是什么:

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

--EOF--

(转载)c语言指针学习的更多相关文章

  1. [转]C语言指针学习经验总结浅谈

    指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...

  2. C语言指针学习

    C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文 一:指针的概念 指针是一个特殊的变量,里面存储的数值是内存里的一个地址. ...

  3. C语言指针学习总结

    上学的时候学习C语言,最烦的就是里面指针,可是指针也恰恰是C语言的灵魂. 最近在重温数据结构的内容,因为大多数据结构的教材都是用C语言描述的,而数据结构中也大量的用到了指针的内容,所以我就在这篇笔记中 ...

  4. c语言指针学习【转】

    前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水, ...

  5. 1.C语言指针学习之外挂篇

    学习了c语言的指针,那么指针能做什么呢,首先,他可以写外挂 首先我们来编写一个dll,挂载到植物大战僵尸上,记住是dll,因为如果你创建一个应用程序,该应用程序是不能操作其他程序的地址的. 第一步,打 ...

  6. c语言指针学习笔记

    指针变量就是存放内存地址的变量.c语言中使用 int *pa; 的方式来定义指针. ` main() int a = 10, b=20, s, t, *pa, *pb,*pc,*pd; pa = &a ...

  7. C语言指针学习(续)

    五.数组和指针的关系 int array[10] = {0,1,2,3,4,5,6,7,8,9},value; ... ... value = array[0];//也可以写成 value = *ar ...

  8. [转载]c语言指针segmentation fault 指针常常错误的小地方

    http://www.cnblogs.com/qingjoin/archive/2012/03/20/2408944.html #include <stdio.h> ] = ] = ] = ...

  9. GO语言学习(十五)Go 语言指针

    Go 语言指针 Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务. 接下来让我们来一步步学习 Go 语言指针. 我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地 ...

随机推荐

  1. jsp、js、html等

    1.一个button标签怎么触发事件: 一般触发事件有两种方式,要么是在html直接绑定,即button标签中不只有class.type和id,还要写onclick=... 还有一种,就是在js代码部 ...

  2. android广告平台介绍

    广告模式:   广告条:最普遍的广告模式,嵌入在应用界面内,用户点击行为会带来收入.   积分墙:应用通过限制功能.去广告等引导用户进入积分墙页面下载广告应用得到积分来换取使用的模式,用户安装完推荐广 ...

  3. [selenium webdriver Java]使用自定义条件同步测试

    Selenium WebDriver可以结合ExpectedCondition类来定义自己期望的条件 创建一个新的ExpectedCondition接口,必须实现apply方法 等待元素出现 publ ...

  4. uva 12296 Pieces and Discs

    题意: 有个矩形,左下角(0,0),左上角(L,W). 思路: 除了圆盘之外,本题的输入也是个PSLG,因此可以按照前面叙述的算法求出各个区域:只需把线段视为直线,用切割凸多边形的方法 :每次读入线段 ...

  5. 编译并使用Lua语言

    Lua是一个小巧的脚本语言,该语言设计的目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. 可扩展性.Lua的扩展性非常卓越,可以通过Lua代码或C代码扩展,很多功能可以通过外部库来扩 ...

  6. 问题-Delphi 中使用TStringList后,报out of memory 的解决方法

    问题现象: 请一段开发个项目 程序调试全部通过但测试时出现个问题 “out of memory” 在长时间运行时!后来终于解决 :很简单其实就是object.create时对象没有释放. 代码如下: ...

  7. python 类和实例

    面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可 ...

  8. CALayer精讲

    前言 CALayer包含在QuartzCore框架中,这是一个跨平台的框架,既可以用在iOS中又可以用在Mac OS X中.后面要学Core Animation就应该先学好Layer(层). 我们看一 ...

  9. IOS-- UIView中的坐标转换

    // 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 - (CGPoint)convertPoint:(CGPoint)point toView:(UI ...

  10. express源码剖析2

    当使用express时,代码会这样写: var express = require('express'); 如果创建一个express的应用,代码会这样写: var app = express(); ...