(转载)c语言指针学习

前言

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

地址

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


#include "stdio.h"

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

// 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) -1;
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 0;
}

这段代码是问你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[5] = {1,2,3,4,5};
int *p = (int *)(&a+1);
printf("%d,%d", *(a+1), *(p-1));
}

答案在此

指针与数组

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


#include "stdio.h"

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

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

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

--EOF--

时间: 2024-08-12 13:59:56

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

c语言指针学习

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

C语言指针学习(转载)

http://blog.chinaunix.net/uid-22889411-id-59688.html c语言中指针学习: 入门介绍: int i=30;//定义一个int型的变量i(两个字节的内存,不同系统可能情况不一样,将这两个字节的内存命名为i,将30转成二进制存入这两个内存中) int *pi;//定义一个指针变量(与定义普通变量并没有什么不同,差异体现在其存入的内容,这个指针的内容是一个指向int型变量的地址.在32位机器中,其长度为4个字节) pi=&i;//将i的地址存入pi中,

c语言指针学习[转]

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

C语言指针学习(续)

五.数组和指针的关系 int array[10] = {0,1,2,3,4,5,6,7,8,9},value; ... ... value = array[0];//也可以写成 value = *array; value = array[3];//也可以写成 value = *(array+3); value = array[4];//也可以写成 value = *(array+4); 上例中,一般而言,数组名array代表数组本身,类型是int[10];如果把array看作指针的话,它指向数组

C语言指针{学习笔记}

按变量地址存取变量值的方式称为直接访问方式: 定义特殊变量用来存放地址,i_pointer的值就是变量i所占用单元的起始地址:存取变量i的值.则要找到存放i的地址的变量,取出地址,然后到地址去取值: i_pointer=&i: 一个变量的地址称为该变量的指针: 如果有一个变量专门用来存放另一变量的地址(指针),称为指针变量: 区别:指针是一个地址,而指针变量是存放地址的变量: 定义指针变量: 如: int *pointer_1;  //int是定义指针变量时必须制定的基类型,指针变量的基类型用来

浅析C语言指针原理

浅谈C语言指针 学习指针,我们必须明白什么是指针.在大多数教材上给出的定义为:"一个变量的地址称为该变量的指针". 由此,首先我们来谈谈计算机内存地址.我们都知道运行一个C语言程序需要将程序从磁盘加载到内存中进行运算.而所谓的运算可以抽象理解为计算机处理器通过地址读取指令.数据的过程.在内存中,每个字节(8位)对应有一个地址,连续存储空间对应连续地址,处理器通过地址可得到存储空间存储的数值.为了方便理解,例举出我们计算机存取变量值的原理:当我们定义一个局部变量例如short a=7时,

C语言基础学习5:字符串与指针

1.字符串的表示形式 (1)用字符数组存放一个字符串,然后输出该字符串. char string[] = "I am happy"; printf("%s",string); (2)用字符指针指向一个字符串. char *string = "I am happy"; printf("%s",string); 2.字符指针作函数参数 (1)用字符数组作参数 void CopyString(char from[], char to

C语言基础学习3:数组与指针

数组元素的指针就是数组元素的地址. 1.指向数组元素的指针 C语言规定数组名(不包括形参数组名,形参数组并不占据实际的内存单元)代表数组中的首元素(即序列为0的元素)的地址. int a[10]; int *p1,*p2; p1 = &a[0]; p2 = a; p1和p2指向同一个数组a[10]. 2.通过指针引用数组元素 按C语言的规定,如果指针变量p已指向数组中的一个元素,则p+1指向同一个数组中的下一个元素,而不是将p的值(地址)简单的加1. 如果p的初值为&a[0],则 (1)

C语言基础学习3:指针

1.地址和指针的概念 一个变量的地址成为该变量的“指针”. 如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”,指针变量的值(即指针变量中存放的值)是地址(即指针). 指针是一个地址,而指针变量是存放地址的变量 2.变量的指针和指向变量的指针变量 2.1指针变量的定义 指针变量的定义:基类型 *指针变量名: int a; int *pointer; pointer = &a; 2.2指针变量的引用 指针变量中只能存放地址,不能将一个整数赋给一个指针变量. “&”和“*