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

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

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

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

//字符串翻转例子 #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语言指针学习的更多相关文章
- [转]C语言指针学习经验总结浅谈
指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...
- C语言指针学习
C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文 一:指针的概念 指针是一个特殊的变量,里面存储的数值是内存里的一个地址. ...
- C语言指针学习总结
上学的时候学习C语言,最烦的就是里面指针,可是指针也恰恰是C语言的灵魂. 最近在重温数据结构的内容,因为大多数据结构的教材都是用C语言描述的,而数据结构中也大量的用到了指针的内容,所以我就在这篇笔记中 ...
- c语言指针学习【转】
前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水, ...
- 1.C语言指针学习之外挂篇
学习了c语言的指针,那么指针能做什么呢,首先,他可以写外挂 首先我们来编写一个dll,挂载到植物大战僵尸上,记住是dll,因为如果你创建一个应用程序,该应用程序是不能操作其他程序的地址的. 第一步,打 ...
- c语言指针学习笔记
指针变量就是存放内存地址的变量.c语言中使用 int *pa; 的方式来定义指针. ` main() int a = 10, b=20, s, t, *pa, *pb,*pc,*pd; pa = &a ...
- C语言指针学习(续)
五.数组和指针的关系 int array[10] = {0,1,2,3,4,5,6,7,8,9},value; ... ... value = array[0];//也可以写成 value = *ar ...
- [转载]c语言指针segmentation fault 指针常常错误的小地方
http://www.cnblogs.com/qingjoin/archive/2012/03/20/2408944.html #include <stdio.h> ] = ] = ] = ...
- GO语言学习(十五)Go 语言指针
Go 语言指针 Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务. 接下来让我们来一步步学习 Go 语言指针. 我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地 ...
随机推荐
- ASP.NET MVC中默认Model Binder绑定Action参数为List、Dictionary等集合的实例
在实际的ASP.NET mvc项目开发中,有时会遇到一个参数是一个List.Dictionary等集合类型的情况,默认的情况ASP.NET MVC框架是怎么为我们绑定ASP.NET MVC的Actio ...
- mkimage的-a 和 –c参数和内核引导
目录 一.mkimage工具简介二.-a参数与-e参数和内核引导的关系三.实例测试 3.1 -a参数与-e参数相同,可以将内核下载到SDRAM的任何地址,然后从这启动 3.2 -a参数与-e参数不同, ...
- POJ 2677 Tour
题意:双调欧几里得旅行商问题.算法导论15-1题,从最左边的点严格从左走到右再从右走到左回到起点,所有点都要走且只走一次,求最短路径. 解法:定义dp[i][j]表示从i走到j的双调路径,分为两种情况 ...
- qtp不识别树结构中的点击事件
qtp不识别树结构中的点击事件,未生成该点击事件的脚本,解决办法: 1.未生成点击"auto分类c1"的脚本 2.点击1.对象库-2.添加对象库-3.选中对象-点击OK,即将该对象 ...
- Go 学习笔记(一)
随着Go的应用越来越火热,自己也终于开始学习了.平时经常用C,看着Go还是比较亲切的.好了,开始. 今天主要是按照书上的内容自己简单的实践了下最基本的输出,以及网页功能,上代码: package ma ...
- Python subprocess Popen
目的:顺序执行进程 在Bash里面类似 a.sh && b.sh && c.sh 先来说下Popen这个函数 class subprocess.Popen(args ...
- $GLOBALS 添加超全局变量
<?php function test() { $foo = "local variable"; echo '$foo in global scope: ' . $GLOBA ...
- IE比Chrome强的一个地方
今天在开发时,调试一个功能.死活显示和同事不一样,他是测试过正常的,我的Chrome显示死活不对. 最后要重新部署了,才想起会不会是缓存的问题.清除Chrome缓存,再一试,一切正常. IE有一个功能 ...
- placeholder 兼容IE9以下版本 包含pasword
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- IEnumerable、IEnumerator与yield的学习
我们知道数组对象可以使用foreach迭代进行遍历,同时我们发现类ArrayList和List也可以使用foreach进行迭代.如果我们自己编写的类也需要使用foreach进行迭代时该怎么办呢? IE ...